xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision df66499a)
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>
35dbb50887SDaniel Borkmann #include <linux/filter.h>
360a708f8fSGustavo F. Padovan 
370a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
380a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
390a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
407ef9fbf0SMarcel Holtmann 
41ac4b7236SMarcel Holtmann #include "smp.h"
427024728eSMarcel Holtmann #include "a2mp.h"
437ef9fbf0SMarcel Holtmann #include "amp.h"
440a708f8fSGustavo F. Padovan 
450f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535
460f1bfe4eSJohan Hedberg 
47d1de6d46SMat Martineau bool disable_ertm;
480a708f8fSGustavo F. Padovan 
49547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
500a708f8fSGustavo F. Padovan 
51b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
52b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
530a708f8fSGustavo F. Padovan 
540a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
550a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
564519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
574519de9aSGustavo F. Padovan 			   void *data);
58e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
595e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
600a708f8fSGustavo F. Padovan 
61d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
62608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
63608bcc6dSMat Martineau 
64a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
654f1654e0SMarcel Holtmann {
66a250e048SJohan Hedberg 	if (link_type == LE_LINK) {
67a250e048SJohan Hedberg 		if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
684f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
694f1654e0SMarcel Holtmann 		else
704f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
714f1654e0SMarcel Holtmann 	}
724f1654e0SMarcel Holtmann 
734f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
744f1654e0SMarcel Holtmann }
754f1654e0SMarcel Holtmann 
76a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
77a250e048SJohan Hedberg {
78a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->src_type);
79a250e048SJohan Hedberg }
80a250e048SJohan Hedberg 
81a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
82a250e048SJohan Hedberg {
83a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->dst_type);
84a250e048SJohan Hedberg }
85a250e048SJohan Hedberg 
860a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8771ba0e56SGustavo F. Padovan 
882d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(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->dcid == cid)
953df91ea2SAndrei Emeltchenko 			return c;
960a708f8fSGustavo F. Padovan 	}
973df91ea2SAndrei Emeltchenko 	return NULL;
98baa7e1faSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
1002d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1012d792818SGustavo Padovan 						   u16 cid)
1020a708f8fSGustavo F. Padovan {
1033df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
104baa7e1faSGustavo F. Padovan 
1053df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1063df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
1073df91ea2SAndrei Emeltchenko 			return c;
1080a708f8fSGustavo F. Padovan 	}
1093df91ea2SAndrei Emeltchenko 	return NULL;
110baa7e1faSGustavo F. Padovan }
1110a708f8fSGustavo F. Padovan 
1120a708f8fSGustavo F. Padovan /* Find channel with given SCID.
113ef191adeSMat Martineau  * Returns locked channel. */
1142d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1152d792818SGustavo Padovan 						 u16 cid)
1160a708f8fSGustavo F. Padovan {
11748454079SGustavo F. Padovan 	struct l2cap_chan *c;
118baa7e1faSGustavo F. Padovan 
1193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
120baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
121ef191adeSMat Martineau 	if (c)
122ef191adeSMat Martineau 		l2cap_chan_lock(c);
1233df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1243df91ea2SAndrei Emeltchenko 
12548454079SGustavo F. Padovan 	return c;
1260a708f8fSGustavo F. Padovan }
1270a708f8fSGustavo F. Padovan 
128b1a130b7SMat Martineau /* Find channel with given DCID.
129b1a130b7SMat Martineau  * Returns locked channel.
130b1a130b7SMat Martineau  */
131b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
132b1a130b7SMat Martineau 						 u16 cid)
133b1a130b7SMat Martineau {
134b1a130b7SMat Martineau 	struct l2cap_chan *c;
135b1a130b7SMat Martineau 
136b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
137b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
138b1a130b7SMat Martineau 	if (c)
139b1a130b7SMat Martineau 		l2cap_chan_lock(c);
140b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
141b1a130b7SMat Martineau 
142b1a130b7SMat Martineau 	return c;
143b1a130b7SMat Martineau }
144b1a130b7SMat Martineau 
1452d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1462d792818SGustavo Padovan 						    u8 ident)
1470a708f8fSGustavo F. Padovan {
1483df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
149baa7e1faSGustavo F. Padovan 
1503df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1513df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1523df91ea2SAndrei Emeltchenko 			return c;
1530a708f8fSGustavo F. Padovan 	}
1543df91ea2SAndrei Emeltchenko 	return NULL;
155baa7e1faSGustavo F. Padovan }
1560a708f8fSGustavo F. Padovan 
1575b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1585b155ef9SMat Martineau 						  u8 ident)
1595b155ef9SMat Martineau {
1605b155ef9SMat Martineau 	struct l2cap_chan *c;
1615b155ef9SMat Martineau 
1625b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1635b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1645b155ef9SMat Martineau 	if (c)
1655b155ef9SMat Martineau 		l2cap_chan_lock(c);
1665b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1675b155ef9SMat Martineau 
1685b155ef9SMat Martineau 	return c;
1695b155ef9SMat Martineau }
1705b155ef9SMat Martineau 
17100f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
17200f62726SLuiz Augusto von Dentz 						      u8 src_type)
1739e4425ffSGustavo F. Padovan {
17423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1759e4425ffSGustavo F. Padovan 
17623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
17700f62726SLuiz Augusto von Dentz 		if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17800f62726SLuiz Augusto von Dentz 			continue;
17900f62726SLuiz Augusto von Dentz 
18000f62726SLuiz Augusto von Dentz 		if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
18100f62726SLuiz Augusto von Dentz 			continue;
18200f62726SLuiz Augusto von Dentz 
1837eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
18423691d75SGustavo F. Padovan 			return c;
1859e4425ffSGustavo F. Padovan 	}
186250938cbSSzymon Janc 	return NULL;
187250938cbSSzymon Janc }
1889e4425ffSGustavo F. Padovan 
1899e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1909e4425ffSGustavo F. Padovan {
19173b2ec18SGustavo F. Padovan 	int err;
19273b2ec18SGustavo F. Padovan 
193333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1949e4425ffSGustavo F. Padovan 
19500f62726SLuiz Augusto von Dentz 	if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
19673b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
19773b2ec18SGustavo F. Padovan 		goto done;
1989e4425ffSGustavo F. Padovan 	}
1999e4425ffSGustavo F. Padovan 
20073b2ec18SGustavo F. Padovan 	if (psm) {
2019e4425ffSGustavo F. Padovan 		chan->psm = psm;
2029e4425ffSGustavo F. Padovan 		chan->sport = psm;
20373b2ec18SGustavo F. Padovan 		err = 0;
20473b2ec18SGustavo F. Padovan 	} else {
20592594a51SJohan Hedberg 		u16 p, start, end, incr;
20692594a51SJohan Hedberg 
20792594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
20892594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
20992594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
21092594a51SJohan Hedberg 			incr = 2;
21192594a51SJohan Hedberg 		} else {
21292594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
21392594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
21492594a51SJohan Hedberg 			incr = 1;
21592594a51SJohan Hedberg 		}
2169e4425ffSGustavo F. Padovan 
21773b2ec18SGustavo F. Padovan 		err = -EINVAL;
21892594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
21900f62726SLuiz Augusto von Dentz 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
22000f62726SLuiz Augusto von Dentz 							 chan->src_type)) {
22173b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
22273b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
22373b2ec18SGustavo F. Padovan 				err = 0;
22473b2ec18SGustavo F. Padovan 				break;
22573b2ec18SGustavo F. Padovan 			}
22673b2ec18SGustavo F. Padovan 	}
22773b2ec18SGustavo F. Padovan 
22873b2ec18SGustavo F. Padovan done:
229333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
23073b2ec18SGustavo F. Padovan 	return err;
2319e4425ffSGustavo F. Padovan }
2326b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2339e4425ffSGustavo F. Padovan 
2349e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2359e4425ffSGustavo F. Padovan {
236333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2379e4425ffSGustavo F. Padovan 
23814824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
23914824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
24014824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
24114824308SJohan Hedberg 
2429e4425ffSGustavo F. Padovan 	chan->scid = scid;
2439e4425ffSGustavo F. Padovan 
244333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2459e4425ffSGustavo F. Padovan 
2469e4425ffSGustavo F. Padovan 	return 0;
2479e4425ffSGustavo F. Padovan }
2489e4425ffSGustavo F. Padovan 
249baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2500a708f8fSGustavo F. Padovan {
251e77af755SJohan Hedberg 	u16 cid, dyn_end;
2520a708f8fSGustavo F. Padovan 
253e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
254e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
255e77af755SJohan Hedberg 	else
256e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
257e77af755SJohan Hedberg 
258ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
259baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2600a708f8fSGustavo F. Padovan 			return cid;
2610a708f8fSGustavo F. Padovan 	}
2620a708f8fSGustavo F. Padovan 
2630a708f8fSGustavo F. Padovan 	return 0;
2640a708f8fSGustavo F. Padovan }
2650a708f8fSGustavo F. Padovan 
266f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26789bc500eSGustavo F. Padovan {
26842d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
269badaaa00SGustavo F. Padovan 	       state_to_string(state));
270badaaa00SGustavo F. Padovan 
27189bc500eSGustavo F. Padovan 	chan->state = state;
27253f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
27389bc500eSGustavo F. Padovan }
27489bc500eSGustavo F. Padovan 
275f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
276f8e73017SGustavo Padovan 						int state, int err)
2772e0052e4SAndrei Emeltchenko {
278f8e73017SGustavo Padovan 	chan->state = state;
27953f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2802e0052e4SAndrei Emeltchenko }
2812e0052e4SAndrei Emeltchenko 
2822e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2832e0052e4SAndrei Emeltchenko {
284f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2852e0052e4SAndrei Emeltchenko }
2862e0052e4SAndrei Emeltchenko 
2874239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2884239d16fSMat Martineau {
2894239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2904239d16fSMat Martineau 	    chan->retrans_timeout) {
2914239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2924239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2934239d16fSMat Martineau 	}
2944239d16fSMat Martineau }
2954239d16fSMat Martineau 
2964239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2974239d16fSMat Martineau {
2984239d16fSMat Martineau 	__clear_retrans_timer(chan);
2994239d16fSMat Martineau 	if (chan->monitor_timeout) {
3004239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
3014239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
3024239d16fSMat Martineau 	}
3034239d16fSMat Martineau }
3044239d16fSMat Martineau 
305608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
306608bcc6dSMat Martineau 					       u16 seq)
307608bcc6dSMat Martineau {
308608bcc6dSMat Martineau 	struct sk_buff *skb;
309608bcc6dSMat Martineau 
310608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
311a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
312608bcc6dSMat Martineau 			return skb;
313608bcc6dSMat Martineau 	}
314608bcc6dSMat Martineau 
315608bcc6dSMat Martineau 	return NULL;
316608bcc6dSMat Martineau }
317608bcc6dSMat Martineau 
3183c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3193c588192SMat Martineau 
3203c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3213c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3223c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3233c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3243c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3253c588192SMat Martineau  * and removed from the head in constant time, without further memory
3263c588192SMat Martineau  * allocs or frees.
3273c588192SMat Martineau  */
3283c588192SMat Martineau 
3293c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3303c588192SMat Martineau {
3313c588192SMat Martineau 	size_t alloc_size, i;
3323c588192SMat Martineau 
3333c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3343c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3353c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3363c588192SMat Martineau 	 */
3373c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3383c588192SMat Martineau 
3396da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3403c588192SMat Martineau 	if (!seq_list->list)
3413c588192SMat Martineau 		return -ENOMEM;
3423c588192SMat Martineau 
3433c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3443c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3453c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3463c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3473c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3483c588192SMat Martineau 
3493c588192SMat Martineau 	return 0;
3503c588192SMat Martineau }
3513c588192SMat Martineau 
3523c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3533c588192SMat Martineau {
3543c588192SMat Martineau 	kfree(seq_list->list);
3553c588192SMat Martineau }
3563c588192SMat Martineau 
3573c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3583c588192SMat Martineau 					   u16 seq)
3593c588192SMat Martineau {
3603c588192SMat Martineau 	/* Constant-time check for list membership */
3613c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3623c588192SMat Martineau }
3633c588192SMat Martineau 
36403a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3653c588192SMat Martineau {
36603a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3673c588192SMat Martineau 	u16 mask = seq_list->mask;
3683c588192SMat Martineau 
3693c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3703c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3713c588192SMat Martineau 
3723c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3733c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3743c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3753c588192SMat Martineau 	}
3763c588192SMat Martineau 
3773c588192SMat Martineau 	return seq;
3783c588192SMat Martineau }
3793c588192SMat Martineau 
3803c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3813c588192SMat Martineau {
3823c588192SMat Martineau 	u16 i;
383f522ae36SGustavo Padovan 
384f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
385f522ae36SGustavo Padovan 		return;
386f522ae36SGustavo Padovan 
3873c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3883c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3893c588192SMat Martineau 
3903c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3913c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3923c588192SMat Martineau }
3933c588192SMat Martineau 
3943c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3953c588192SMat Martineau {
3963c588192SMat Martineau 	u16 mask = seq_list->mask;
3973c588192SMat Martineau 
3983c588192SMat Martineau 	/* All appends happen in constant time */
3993c588192SMat Martineau 
400f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
401f522ae36SGustavo Padovan 		return;
402f522ae36SGustavo Padovan 
4033c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4043c588192SMat Martineau 		seq_list->head = seq;
4053c588192SMat Martineau 	else
4063c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
4073c588192SMat Martineau 
4083c588192SMat Martineau 	seq_list->tail = seq;
4093c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4103c588192SMat Martineau }
4113c588192SMat Martineau 
412721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
413ab07801dSGustavo F. Padovan {
414721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
415721c4181SGustavo F. Padovan 					       chan_timer.work);
4163df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
417ab07801dSGustavo F. Padovan 	int reason;
418ab07801dSGustavo F. Padovan 
419e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
420ab07801dSGustavo F. Padovan 
4213df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4226be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
423ab07801dSGustavo F. Padovan 
42489bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
425ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
42689bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
427ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
428ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
429ab07801dSGustavo F. Padovan 	else
430ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
431ab07801dSGustavo F. Padovan 
4320f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
433ab07801dSGustavo F. Padovan 
4346be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
435ab07801dSGustavo F. Padovan 
43680b98027SGustavo Padovan 	chan->ops->close(chan);
4373df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4383df91ea2SAndrei Emeltchenko 
439371fd835SUlisses Furquim 	l2cap_chan_put(chan);
440ab07801dSGustavo F. Padovan }
441ab07801dSGustavo F. Padovan 
442eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4430a708f8fSGustavo F. Padovan {
44448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4450a708f8fSGustavo F. Padovan 
44648454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
44748454079SGustavo F. Padovan 	if (!chan)
44848454079SGustavo F. Padovan 		return NULL;
4490a708f8fSGustavo F. Padovan 
450c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
451c03b355eSAndrei Emeltchenko 
452ff714119SJohan Hedberg 	/* Set default lock nesting level */
453ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
454ff714119SJohan Hedberg 
455333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
45623691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
457333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
45823691d75SGustavo F. Padovan 
459721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
460ab07801dSGustavo F. Padovan 
46189bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
46289bc500eSGustavo F. Padovan 
463144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
46471ba0e56SGustavo F. Padovan 
4652827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4662827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4672827011fSMat Martineau 
468eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
469abc545b8SSzymon Janc 
47048454079SGustavo F. Padovan 	return chan;
4710a708f8fSGustavo F. Padovan }
4726b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4730a708f8fSGustavo F. Padovan 
474144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4756ff5abbfSGustavo F. Padovan {
476144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
477144ad330SSyam Sidhardhan 
4784af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4794af66c69SJaganath Kanakkassery 
480333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
48123691d75SGustavo F. Padovan 	list_del(&chan->global_l);
482333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
48323691d75SGustavo F. Padovan 
4844af66c69SJaganath Kanakkassery 	kfree(chan);
4856ff5abbfSGustavo F. Padovan }
4866ff5abbfSGustavo F. Padovan 
48730648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
48830648372SJaganath Kanakkassery {
4892c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
49030648372SJaganath Kanakkassery 
491144ad330SSyam Sidhardhan 	kref_get(&c->kref);
49230648372SJaganath Kanakkassery }
49330648372SJaganath Kanakkassery 
49430648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
49530648372SJaganath Kanakkassery {
4962c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
49730648372SJaganath Kanakkassery 
498144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
49930648372SJaganath Kanakkassery }
5006b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
50130648372SJaganath Kanakkassery 
502bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
503bd4b1653SAndrei Emeltchenko {
504bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
505bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
506bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
507bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5086a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5096a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
510c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
511bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5126a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5136a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5146a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5156a5e8165SJukka Rissanen 	chan->conf_state = 0;
516bd4b1653SAndrei Emeltchenko 
517bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
518bd4b1653SAndrei Emeltchenko }
5196b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
520bd4b1653SAndrei Emeltchenko 
521ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
52238319713SJohan Hedberg {
5230ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5240ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5250ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
526ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
527fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
528fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
52996cd8eaaSLuiz Augusto von Dentz 	/* Give enough credits for a full packet */
53096cd8eaaSLuiz Augusto von Dentz 	chan->rx_credits = (chan->imtu / chan->mps) + 1;
5310ce43ce6SJohan Hedberg 
5320ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
53338319713SJohan Hedberg }
53438319713SJohan Hedberg 
53593c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5360a708f8fSGustavo F. Padovan {
5370a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
538097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5390a708f8fSGustavo F. Padovan 
5409f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5410a708f8fSGustavo F. Padovan 
5428c1d787bSGustavo F. Padovan 	chan->conn = conn;
5430a708f8fSGustavo F. Padovan 
5445491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5455491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
5460a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
547fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
54821626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
5490c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
5505491120eSAndrei Emeltchenko 		break;
5515491120eSAndrei Emeltchenko 
5525491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5530a708f8fSGustavo F. Padovan 		/* Connectionless socket */
554fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
555fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5560c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5575491120eSAndrei Emeltchenko 		break;
5585491120eSAndrei Emeltchenko 
5592338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
5602338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
561416fa752SAndrei Emeltchenko 		break;
562416fa752SAndrei Emeltchenko 
5635491120eSAndrei Emeltchenko 	default:
5640a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
565fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
566fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5670c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5680a708f8fSGustavo F. Padovan 	}
5690a708f8fSGustavo F. Padovan 
5708f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5718f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5728f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5738f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5748f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5758936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5768f7975b1SAndrei Emeltchenko 
577371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
578baa7e1faSGustavo F. Padovan 
579c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
580c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
581c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
5825ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
5835ee9891dSJohan Hedberg 
5843df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
585643162a8SAndrei Emeltchenko }
586643162a8SAndrei Emeltchenko 
587466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
588643162a8SAndrei Emeltchenko {
589643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
590643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5913df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5920a708f8fSGustavo F. Padovan }
5930a708f8fSGustavo F. Padovan 
594466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5950a708f8fSGustavo F. Padovan {
5968c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5970a708f8fSGustavo F. Padovan 
598c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5990a708f8fSGustavo F. Padovan 
60049d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
60149d11741SJohan Hedberg 	       state_to_string(chan->state));
6020a708f8fSGustavo F. Padovan 
60372847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
60472847ce0SJohan Hedberg 
6050a708f8fSGustavo F. Padovan 	if (conn) {
60656f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
607baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6083df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6093d57dc68SGustavo F. Padovan 
610371fd835SUlisses Furquim 		l2cap_chan_put(chan);
611baa7e1faSGustavo F. Padovan 
6128c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6133cabbfdaSAndrei Emeltchenko 
614c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
615c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
616c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
617c16900cfSJohan Hedberg 		 */
618c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
619c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
62076a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
62156f60984SAndrei Emeltchenko 
62256f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
62356f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6240a708f8fSGustavo F. Padovan 	}
6250a708f8fSGustavo F. Padovan 
626419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
627419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
628419e08c1SAndrei Emeltchenko 
629419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
630419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
631419e08c1SAndrei Emeltchenko 	}
632419e08c1SAndrei Emeltchenko 
6332827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6346ff5abbfSGustavo F. Padovan 		return;
6352ead70b8SGustavo F. Padovan 
636ee556f66SGustavo Padovan 	switch(chan->mode) {
637ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
638ee556f66SGustavo Padovan 		break;
6390a708f8fSGustavo F. Padovan 
64038319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
641177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
64238319713SJohan Hedberg 		break;
64338319713SJohan Hedberg 
644ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6451a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6461a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6471a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6480a708f8fSGustavo F. Padovan 
649f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6500a708f8fSGustavo F. Padovan 
6513c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6523c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
653ee556f66SGustavo Padovan 
654ee556f66SGustavo Padovan 		/* fall through */
655ee556f66SGustavo Padovan 
656ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
657ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
658ee556f66SGustavo Padovan 		break;
6590a708f8fSGustavo F. Padovan 	}
660ee556f66SGustavo Padovan 
661ee556f66SGustavo Padovan 	return;
6620a708f8fSGustavo F. Padovan }
6636b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
6640a708f8fSGustavo F. Padovan 
665f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
666387a33e3SJohan Hedberg {
667f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
668f3d82d0cSJohan Hedberg 					       id_addr_update_work);
669f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
670387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
671387a33e3SJohan Hedberg 
672387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
673387a33e3SJohan Hedberg 
674387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
675387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
676387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
677a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
678387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
679387a33e3SJohan Hedberg 	}
680387a33e3SJohan Hedberg 
681387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
682387a33e3SJohan Hedberg }
683387a33e3SJohan Hedberg 
68427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
68527e2d4c8SJohan Hedberg {
68627e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
68727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
68827e2d4c8SJohan Hedberg 	u16 result;
68927e2d4c8SJohan Hedberg 
69027e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
691571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
69227e2d4c8SJohan Hedberg 	else
693571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
69427e2d4c8SJohan Hedberg 
69527e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
69627e2d4c8SJohan Hedberg 
69727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
69827e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
6993916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
7000cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
70127e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
70227e2d4c8SJohan Hedberg 
70327e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
70427e2d4c8SJohan Hedberg 		       &rsp);
70527e2d4c8SJohan Hedberg }
70627e2d4c8SJohan Hedberg 
707791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
708791d60f7SJohan Hedberg {
709791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
710791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
711791d60f7SJohan Hedberg 	u16 result;
712791d60f7SJohan Hedberg 
713791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
714791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
715791d60f7SJohan Hedberg 	else
716791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
717791d60f7SJohan Hedberg 
718791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
719791d60f7SJohan Hedberg 
720791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
721791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
722791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
723dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
724791d60f7SJohan Hedberg 
725791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
726791d60f7SJohan Hedberg }
727791d60f7SJohan Hedberg 
7280f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
7294519de9aSGustavo F. Padovan {
7304519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7314519de9aSGustavo F. Padovan 
7327eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
7334519de9aSGustavo F. Padovan 
73489bc500eSGustavo F. Padovan 	switch (chan->state) {
7354519de9aSGustavo F. Padovan 	case BT_LISTEN:
736c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7374519de9aSGustavo F. Padovan 		break;
7384519de9aSGustavo F. Padovan 
7394519de9aSGustavo F. Padovan 	case BT_CONNECTED:
7404519de9aSGustavo F. Padovan 	case BT_CONFIG:
7417b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
7428d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7435e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
7444519de9aSGustavo F. Padovan 		} else
7454519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
7464519de9aSGustavo F. Padovan 		break;
7474519de9aSGustavo F. Padovan 
7484519de9aSGustavo F. Padovan 	case BT_CONNECT2:
749791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
750791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
751791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
75227e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
75327e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7544519de9aSGustavo F. Padovan 		}
7554519de9aSGustavo F. Padovan 
7564519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7574519de9aSGustavo F. Padovan 		break;
7584519de9aSGustavo F. Padovan 
7594519de9aSGustavo F. Padovan 	case BT_CONNECT:
7604519de9aSGustavo F. Padovan 	case BT_DISCONN:
7614519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7624519de9aSGustavo F. Padovan 		break;
7634519de9aSGustavo F. Padovan 
7644519de9aSGustavo F. Padovan 	default:
765c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7664519de9aSGustavo F. Padovan 		break;
7674519de9aSGustavo F. Padovan 	}
7684519de9aSGustavo F. Padovan }
7696b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
7704519de9aSGustavo F. Padovan 
7714343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7720a708f8fSGustavo F. Padovan {
7736a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7746a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7754343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7760a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7777d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
7780a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7790a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7800a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7810a708f8fSGustavo F. Padovan 		default:
7820a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7830a708f8fSGustavo F. Padovan 		}
7846a974b50SMarcel Holtmann 		break;
7853124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
786dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
7873124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7883124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7893124b843SMarcel Holtmann 		}
7907d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
7917d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
7923124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7933124b843SMarcel Holtmann 		else
7943124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7953124b843SMarcel Holtmann 		break;
7966a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
797dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
7984343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7994343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
8000a708f8fSGustavo F. Padovan 
8017d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
8027d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
8030a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
8040a708f8fSGustavo F. Padovan 			else
8050a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
8066a974b50SMarcel Holtmann 		}
8076a974b50SMarcel Holtmann 		/* fall through */
8086a974b50SMarcel Holtmann 	default:
8094343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8100a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8117d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8120a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
8130a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8140a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
8150a708f8fSGustavo F. Padovan 		default:
8160a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8170a708f8fSGustavo F. Padovan 		}
8186a974b50SMarcel Holtmann 		break;
8190a708f8fSGustavo F. Padovan 	}
8200a708f8fSGustavo F. Padovan }
8210a708f8fSGustavo F. Padovan 
8220a708f8fSGustavo F. Padovan /* Service level security */
823e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
8240a708f8fSGustavo F. Padovan {
8258c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8260a708f8fSGustavo F. Padovan 	__u8 auth_type;
8270a708f8fSGustavo F. Padovan 
828a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
829a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
830a17de2feSJohan Hedberg 
8314343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
8320a708f8fSGustavo F. Padovan 
833e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
834e7cafc45SJohan Hedberg 				 initiator);
8350a708f8fSGustavo F. Padovan }
8360a708f8fSGustavo F. Padovan 
837b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
8380a708f8fSGustavo F. Padovan {
8390a708f8fSGustavo F. Padovan 	u8 id;
8400a708f8fSGustavo F. Padovan 
8410a708f8fSGustavo F. Padovan 	/* Get next available identificator.
8420a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
8430a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
8440a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
8450a708f8fSGustavo F. Padovan 	 */
8460a708f8fSGustavo F. Padovan 
8475a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
8480a708f8fSGustavo F. Padovan 
8490a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
8500a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
8510a708f8fSGustavo F. Padovan 
8520a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
8530a708f8fSGustavo F. Padovan 
8545a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
8550a708f8fSGustavo F. Padovan 
8560a708f8fSGustavo F. Padovan 	return id;
8570a708f8fSGustavo F. Padovan }
8580a708f8fSGustavo F. Padovan 
8592d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8602d792818SGustavo Padovan 			   void *data)
8610a708f8fSGustavo F. Padovan {
8620a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8630a708f8fSGustavo F. Padovan 	u8 flags;
8640a708f8fSGustavo F. Padovan 
8650a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8660a708f8fSGustavo F. Padovan 
8670a708f8fSGustavo F. Padovan 	if (!skb)
8680a708f8fSGustavo F. Padovan 		return;
8690a708f8fSGustavo F. Padovan 
870f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
871f6af675eSSteven Walter 	 * not support auto-flushing packets) */
872f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
873f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
8740a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8750a708f8fSGustavo F. Padovan 	else
8760a708f8fSGustavo F. Padovan 		flags = ACL_START;
8770a708f8fSGustavo F. Padovan 
87814b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8795e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
88014b12d0bSJaikumar Ganesh 
88173d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8820a708f8fSGustavo F. Padovan }
8830a708f8fSGustavo F. Padovan 
88402b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
88502b0fbb9SMat Martineau {
88602b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
88702b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
88802b0fbb9SMat Martineau }
88902b0fbb9SMat Martineau 
89073d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
89173d80debSLuiz Augusto von Dentz {
89273d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
89373d80debSLuiz Augusto von Dentz 	u16 flags;
89473d80debSLuiz Augusto von Dentz 
89573d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
89673d80debSLuiz Augusto von Dentz 	       skb->priority);
89773d80debSLuiz Augusto von Dentz 
898d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
899d5f8a75dSMat Martineau 		if (chan->hs_hchan)
900d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
901d5f8a75dSMat Martineau 		else
902d5f8a75dSMat Martineau 			kfree_skb(skb);
903d5f8a75dSMat Martineau 
904d5f8a75dSMat Martineau 		return;
905d5f8a75dSMat Martineau 	}
906d5f8a75dSMat Martineau 
907f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
908f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
909f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
910f6af675eSSteven Walter 	 */
911f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
912f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
913f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
91473d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
91573d80debSLuiz Augusto von Dentz 	else
91673d80debSLuiz Augusto von Dentz 		flags = ACL_START;
91773d80debSLuiz Augusto von Dentz 
91873d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
91973d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
9200a708f8fSGustavo F. Padovan }
9210a708f8fSGustavo F. Padovan 
922b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
923b5c6aaedSMat Martineau {
924b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
925b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
926b5c6aaedSMat Martineau 
927b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
928b5c6aaedSMat Martineau 		/* S-Frame */
929b5c6aaedSMat Martineau 		control->sframe = 1;
930b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
931b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
932b5c6aaedSMat Martineau 
933b5c6aaedSMat Martineau 		control->sar = 0;
934b5c6aaedSMat Martineau 		control->txseq = 0;
935b5c6aaedSMat Martineau 	} else {
936b5c6aaedSMat Martineau 		/* I-Frame */
937b5c6aaedSMat Martineau 		control->sframe = 0;
938b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
939b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
940b5c6aaedSMat Martineau 
941b5c6aaedSMat Martineau 		control->poll = 0;
942b5c6aaedSMat Martineau 		control->super = 0;
943b5c6aaedSMat Martineau 	}
944b5c6aaedSMat Martineau }
945b5c6aaedSMat Martineau 
946b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
947b5c6aaedSMat Martineau {
948b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
949b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
950b5c6aaedSMat Martineau 
951b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
952b5c6aaedSMat Martineau 		/* S-Frame */
953b5c6aaedSMat Martineau 		control->sframe = 1;
954b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
955b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
956b5c6aaedSMat Martineau 
957b5c6aaedSMat Martineau 		control->sar = 0;
958b5c6aaedSMat Martineau 		control->txseq = 0;
959b5c6aaedSMat Martineau 	} else {
960b5c6aaedSMat Martineau 		/* I-Frame */
961b5c6aaedSMat Martineau 		control->sframe = 0;
962b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
963b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
964b5c6aaedSMat Martineau 
965b5c6aaedSMat Martineau 		control->poll = 0;
966b5c6aaedSMat Martineau 		control->super = 0;
967b5c6aaedSMat Martineau 	}
968b5c6aaedSMat Martineau }
969b5c6aaedSMat Martineau 
970b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
971b5c6aaedSMat Martineau 				    struct sk_buff *skb)
972b5c6aaedSMat Martineau {
973b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
974b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
975a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
976cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
977b5c6aaedSMat Martineau 	} else {
978b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
979a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
980cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
981b5c6aaedSMat Martineau 	}
982b5c6aaedSMat Martineau }
983b5c6aaedSMat Martineau 
984b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
985b5c6aaedSMat Martineau {
986b5c6aaedSMat Martineau 	u32 packed;
987b5c6aaedSMat Martineau 
988b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
989b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
990b5c6aaedSMat Martineau 
991b5c6aaedSMat Martineau 	if (control->sframe) {
992b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
993b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
994b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
995b5c6aaedSMat Martineau 	} else {
996b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
997b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
998b5c6aaedSMat Martineau 	}
999b5c6aaedSMat Martineau 
1000b5c6aaedSMat Martineau 	return packed;
1001b5c6aaedSMat Martineau }
1002b5c6aaedSMat Martineau 
1003b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1004b5c6aaedSMat Martineau {
1005b5c6aaedSMat Martineau 	u16 packed;
1006b5c6aaedSMat Martineau 
1007b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1008b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1009b5c6aaedSMat Martineau 
1010b5c6aaedSMat Martineau 	if (control->sframe) {
1011b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1012b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1013b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1014b5c6aaedSMat Martineau 	} else {
1015b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1016b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1017b5c6aaedSMat Martineau 	}
1018b5c6aaedSMat Martineau 
1019b5c6aaedSMat Martineau 	return packed;
1020b5c6aaedSMat Martineau }
1021b5c6aaedSMat Martineau 
1022b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1023b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1024b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1025b5c6aaedSMat Martineau {
1026b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1027b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1028b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1029b5c6aaedSMat Martineau 	} else {
1030b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1031b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1032b5c6aaedSMat Martineau 	}
1033b5c6aaedSMat Martineau }
1034b5c6aaedSMat Martineau 
1035ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1036ba7aa64fSGustavo Padovan {
1037ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1038ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1039ba7aa64fSGustavo Padovan 	else
1040ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1041ba7aa64fSGustavo Padovan }
1042ba7aa64fSGustavo Padovan 
1043a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1044a67d7f6fSMat Martineau 					       u32 control)
10450a708f8fSGustavo F. Padovan {
10460a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
10470a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1048ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
10490a708f8fSGustavo F. Padovan 
10500a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
105103a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
10520a708f8fSGustavo F. Padovan 
1053a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
10540a708f8fSGustavo F. Padovan 
10550a708f8fSGustavo F. Padovan 	if (!skb)
1056a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
10570a708f8fSGustavo F. Padovan 
10584df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
10590a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1060fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
106188843ab0SAndrei Emeltchenko 
1062a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1063a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1064a67d7f6fSMat Martineau 	else
1065a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10660a708f8fSGustavo F. Padovan 
106747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1068a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
106903a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10700a708f8fSGustavo F. Padovan 	}
10710a708f8fSGustavo F. Padovan 
107273d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1073a67d7f6fSMat Martineau 	return skb;
1074a67d7f6fSMat Martineau }
1075a67d7f6fSMat Martineau 
1076a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1077a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1078a67d7f6fSMat Martineau {
1079a67d7f6fSMat Martineau 	struct sk_buff *skb;
1080a67d7f6fSMat Martineau 	u32 control_field;
1081a67d7f6fSMat Martineau 
1082a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1083a67d7f6fSMat Martineau 
1084a67d7f6fSMat Martineau 	if (!control->sframe)
1085a67d7f6fSMat Martineau 		return;
1086a67d7f6fSMat Martineau 
1087b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1088b99e13adSMat Martineau 		return;
1089b99e13adSMat Martineau 
1090a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1091a67d7f6fSMat Martineau 	    !control->poll)
1092a67d7f6fSMat Martineau 		control->final = 1;
1093a67d7f6fSMat Martineau 
1094a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1095a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1096a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1097a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1098a67d7f6fSMat Martineau 
1099a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1100a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1101a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1102a67d7f6fSMat Martineau 	}
1103a67d7f6fSMat Martineau 
1104a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1105a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1106a67d7f6fSMat Martineau 
1107a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1108a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1109a67d7f6fSMat Martineau 	else
1110a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1111a67d7f6fSMat Martineau 
1112a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1113a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
111473d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
11150a708f8fSGustavo F. Padovan }
11160a708f8fSGustavo F. Padovan 
1117c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11180a708f8fSGustavo F. Padovan {
1119c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
11200a708f8fSGustavo F. Padovan 
1121c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1122c9e3d5e0SMat Martineau 
1123c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1124c9e3d5e0SMat Martineau 	control.sframe = 1;
1125c9e3d5e0SMat Martineau 	control.poll = poll;
1126c9e3d5e0SMat Martineau 
1127c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1128c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1129c9e3d5e0SMat Martineau 	else
1130c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1131c9e3d5e0SMat Martineau 
1132c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1133c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
11340a708f8fSGustavo F. Padovan }
11350a708f8fSGustavo F. Padovan 
1136b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
11370a708f8fSGustavo F. Padovan {
11385ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
11395ff6f34dSJohan Hedberg 		return true;
11405ff6f34dSJohan Hedberg 
1141c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
11420a708f8fSGustavo F. Padovan }
11430a708f8fSGustavo F. Padovan 
114493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
114593c3e8f5SAndrei Emeltchenko {
114693c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11471df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
11481df7b17aSMarcel Holtmann 	bool amp_available = false;
114993c3e8f5SAndrei Emeltchenko 
11500bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
11511df7b17aSMarcel Holtmann 		return false;
11521df7b17aSMarcel Holtmann 
11530bd49fc7SJohan Hedberg 	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
11541df7b17aSMarcel Holtmann 		return false;
11551df7b17aSMarcel Holtmann 
11561df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
11571df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
11581df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
11591df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
11601df7b17aSMarcel Holtmann 			amp_available = true;
11611df7b17aSMarcel Holtmann 			break;
11621df7b17aSMarcel Holtmann 		}
11631df7b17aSMarcel Holtmann 	}
11641df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
11651df7b17aSMarcel Holtmann 
11661df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11671df7b17aSMarcel Holtmann 		return amp_available;
1168848566b3SMarcel Holtmann 
116993c3e8f5SAndrei Emeltchenko 	return false;
117093c3e8f5SAndrei Emeltchenko }
117193c3e8f5SAndrei Emeltchenko 
11725ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11735ce66b59SAndrei Emeltchenko {
11745ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11755ce66b59SAndrei Emeltchenko 	return true;
11765ce66b59SAndrei Emeltchenko }
11775ce66b59SAndrei Emeltchenko 
11782766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11799b27f350SAndrei Emeltchenko {
11809b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11819b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11829b27f350SAndrei Emeltchenko 
11839b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11849b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11859b27f350SAndrei Emeltchenko 
11869b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11879b27f350SAndrei Emeltchenko 
11889b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11899b27f350SAndrei Emeltchenko 
11909b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11919b27f350SAndrei Emeltchenko }
11929b27f350SAndrei Emeltchenko 
11938eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11948eb200bdSMat Martineau {
11958eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11968eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11978eb200bdSMat Martineau 	req.psm  = chan->psm;
11988eb200bdSMat Martineau 	req.amp_id = amp_id;
11998eb200bdSMat Martineau 
12008eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
12018eb200bdSMat Martineau 
12028eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
12038eb200bdSMat Martineau 		       sizeof(req), &req);
12048eb200bdSMat Martineau }
12058eb200bdSMat Martineau 
120602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
120702b0fbb9SMat Martineau {
120802b0fbb9SMat Martineau 	struct sk_buff *skb;
120902b0fbb9SMat Martineau 
121002b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
121102b0fbb9SMat Martineau 
121202b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
121302b0fbb9SMat Martineau 		return;
121402b0fbb9SMat Martineau 
121502b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
121602b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
121702b0fbb9SMat Martineau 	__clear_ack_timer(chan);
121802b0fbb9SMat Martineau 
121902b0fbb9SMat Martineau 	chan->retry_count = 0;
122002b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
1221a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.retries)
1222a4368ff3SJohan Hedberg 			bt_cb(skb)->l2cap.retries = 1;
122302b0fbb9SMat Martineau 		else
122402b0fbb9SMat Martineau 			break;
122502b0fbb9SMat Martineau 	}
122602b0fbb9SMat Martineau 
122702b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
122802b0fbb9SMat Martineau 
122902b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
123002b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
123102b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
123202b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
123302b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
123402b0fbb9SMat Martineau 
123502b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
123602b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
123702b0fbb9SMat Martineau 
123802b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
123902b0fbb9SMat Martineau }
124002b0fbb9SMat Martineau 
12415f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
12425f3847a4SMat Martineau {
12435f3847a4SMat Martineau 	u8 move_role = chan->move_role;
12445f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
12455f3847a4SMat Martineau 
12465f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
12475f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
12485f3847a4SMat Martineau 
12495f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
12505f3847a4SMat Martineau 		return;
12515f3847a4SMat Martineau 
12525f3847a4SMat Martineau 	switch (move_role) {
12535f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
12545f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
12555f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
12565f3847a4SMat Martineau 		break;
12575f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
12585f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
12595f3847a4SMat Martineau 		break;
12605f3847a4SMat Martineau 	}
12615f3847a4SMat Martineau }
12625f3847a4SMat Martineau 
12639f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12649f0caeb1SVinicius Costa Gomes {
1265315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1266315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1267315917e0SJohan Hedberg 	 * procedure is complete.
1268315917e0SJohan Hedberg 	 */
1269315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1270315917e0SJohan Hedberg 		return;
1271315917e0SJohan Hedberg 
12722827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12739f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12749f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12759f0caeb1SVinicius Costa Gomes 
12760ce43ce6SJohan Hedberg 	if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits)
12770ce43ce6SJohan Hedberg 		chan->ops->suspend(chan);
1278177f8f2bSJohan Hedberg 
127954a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12809f0caeb1SVinicius Costa Gomes 
128154a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12829f0caeb1SVinicius Costa Gomes }
12839f0caeb1SVinicius Costa Gomes 
1284f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1285f1496deeSJohan Hedberg {
1286f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1287f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1288f1496deeSJohan Hedberg 
1289595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1290595177f3SJohan Hedberg 		return;
1291595177f3SJohan Hedberg 
1292ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1293fe149310SLuiz Augusto von Dentz 
1294f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1295f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1296f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
12973916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
12980cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1299f1496deeSJohan Hedberg 
1300f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1301f1496deeSJohan Hedberg 
1302f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1303f1496deeSJohan Hedberg 		       sizeof(req), &req);
1304f1496deeSJohan Hedberg }
1305f1496deeSJohan Hedberg 
1306f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1307f1496deeSJohan Hedberg {
1308f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1309f1496deeSJohan Hedberg 
1310f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1311f1496deeSJohan Hedberg 		return;
1312f1496deeSJohan Hedberg 
1313f1496deeSJohan Hedberg 	if (!chan->psm) {
1314f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1315f1496deeSJohan Hedberg 		return;
1316f1496deeSJohan Hedberg 	}
1317f1496deeSJohan Hedberg 
1318f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1319f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1320f1496deeSJohan Hedberg }
1321f1496deeSJohan Hedberg 
132293c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
132393c3e8f5SAndrei Emeltchenko {
132493c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
132593c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
132693c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1327f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1328f1496deeSJohan Hedberg 		l2cap_le_start(chan);
132993c3e8f5SAndrei Emeltchenko 	} else {
133093c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
133193c3e8f5SAndrei Emeltchenko 	}
133293c3e8f5SAndrei Emeltchenko }
133393c3e8f5SAndrei Emeltchenko 
1334aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
13350a708f8fSGustavo F. Padovan {
13360a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1337aeaeb4bbSJohan Hedberg 
1338aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1339aeaeb4bbSJohan Hedberg 		return;
1340aeaeb4bbSJohan Hedberg 
1341dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
13420a708f8fSGustavo F. Padovan 
13430a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
13440a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
13450a708f8fSGustavo F. Padovan 
1346ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
13470a708f8fSGustavo F. Padovan 
13482d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
13492d792818SGustavo Padovan 		       sizeof(req), &req);
13500a708f8fSGustavo F. Padovan }
1351aeaeb4bbSJohan Hedberg 
1352693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1353693cd8ceSMarcel Holtmann {
1354693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1355693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1356693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1357693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1358693cd8ceSMarcel Holtmann 	 *
1359693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1360693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1361693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1362693cd8ceSMarcel Holtmann 	 */
1363693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
136458a96fc3SMarcel Holtmann 		hcon->enc_key_size >= hcon->hdev->min_enc_key_size);
1365693cd8ceSMarcel Holtmann }
1366693cd8ceSMarcel Holtmann 
1367aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1368aeaeb4bbSJohan Hedberg {
1369aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1370aeaeb4bbSJohan Hedberg 
1371aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1372aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1373aeaeb4bbSJohan Hedberg 		return;
1374aeaeb4bbSJohan Hedberg 	}
1375aeaeb4bbSJohan Hedberg 
1376aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1377aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1378aeaeb4bbSJohan Hedberg 		return;
1379aeaeb4bbSJohan Hedberg 	}
1380aeaeb4bbSJohan Hedberg 
1381aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1382aeaeb4bbSJohan Hedberg 		return;
1383aeaeb4bbSJohan Hedberg 
1384693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1385693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1386693cd8ceSMarcel Holtmann 		return;
1387693cd8ceSMarcel Holtmann 
1388693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1389aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1390693cd8ceSMarcel Holtmann 	else
1391693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
13920a708f8fSGustavo F. Padovan }
13930a708f8fSGustavo F. Padovan 
13940a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
13950a708f8fSGustavo F. Padovan {
13960a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
13970a708f8fSGustavo F. Padovan 	if (!disable_ertm)
13980a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
13990a708f8fSGustavo F. Padovan 
14000a708f8fSGustavo F. Padovan 	switch (mode) {
14010a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
14020a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
14030a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
14040a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
14050a708f8fSGustavo F. Padovan 	default:
14060a708f8fSGustavo F. Padovan 		return 0x00;
14070a708f8fSGustavo F. Padovan 	}
14080a708f8fSGustavo F. Padovan }
14090a708f8fSGustavo F. Padovan 
14105e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
14110a708f8fSGustavo F. Padovan {
14125e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
14130a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
14140a708f8fSGustavo F. Padovan 
14150a708f8fSGustavo F. Padovan 	if (!conn)
14160a708f8fSGustavo F. Padovan 		return;
14170a708f8fSGustavo F. Padovan 
1418aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
14191a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
14201a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
14211a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
14220a708f8fSGustavo F. Padovan 	}
14230a708f8fSGustavo F. Padovan 
14242338a7e0SJohan Hedberg 	if (chan->scid == L2CAP_CID_A2MP) {
1425d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1426416fa752SAndrei Emeltchenko 		return;
1427416fa752SAndrei Emeltchenko 	}
1428416fa752SAndrei Emeltchenko 
1429fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1430fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
14312d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
14322d792818SGustavo Padovan 		       sizeof(req), &req);
14330a708f8fSGustavo F. Padovan 
1434f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
14350a708f8fSGustavo F. Padovan }
14360a708f8fSGustavo F. Padovan 
14370a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
14380a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
14390a708f8fSGustavo F. Padovan {
14403df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
14410a708f8fSGustavo F. Padovan 
14420a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
14430a708f8fSGustavo F. Padovan 
14443df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
14450a708f8fSGustavo F. Padovan 
14463df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
14476be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
14480a708f8fSGustavo F. Padovan 
1449715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1450aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
14516be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
14520a708f8fSGustavo F. Padovan 			continue;
14530a708f8fSGustavo F. Padovan 		}
14540a708f8fSGustavo F. Padovan 
145589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1456e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1457b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
14586be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14590a708f8fSGustavo F. Padovan 				continue;
14600a708f8fSGustavo F. Padovan 			}
14610a708f8fSGustavo F. Padovan 
1462c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1463c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1464c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
14650f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
14666be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14670a708f8fSGustavo F. Padovan 				continue;
14680a708f8fSGustavo F. Padovan 			}
14690a708f8fSGustavo F. Padovan 
1470693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
147193c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1472693cd8ceSMarcel Holtmann 			else
1473693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
14740a708f8fSGustavo F. Padovan 
147589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
14760a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
14770a708f8fSGustavo F. Padovan 			char buf[128];
1478fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1479fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
14800a708f8fSGustavo F. Padovan 
1481e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1482bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1483dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1484dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
14852dc4e510SGustavo Padovan 					chan->ops->defer(chan);
14860a708f8fSGustavo F. Padovan 
14870a708f8fSGustavo F. Padovan 				} else {
1488acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1489dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1490dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
14910a708f8fSGustavo F. Padovan 				}
14920a708f8fSGustavo F. Padovan 			} else {
1493dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1494dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
14950a708f8fSGustavo F. Padovan 			}
14960a708f8fSGustavo F. Padovan 
1497fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1498fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
14990a708f8fSGustavo F. Padovan 
1500c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
15010a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
15026be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
15030a708f8fSGustavo F. Padovan 				continue;
15040a708f8fSGustavo F. Padovan 			}
15050a708f8fSGustavo F. Padovan 
1506c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
15070a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1508e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
150973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
15100a708f8fSGustavo F. Padovan 		}
15110a708f8fSGustavo F. Padovan 
15126be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15130a708f8fSGustavo F. Padovan 	}
15140a708f8fSGustavo F. Padovan 
15153df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15160a708f8fSGustavo F. Padovan }
15170a708f8fSGustavo F. Padovan 
1518b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1519b62f328bSVille Tervo {
1520cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1521dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1522b62f328bSVille Tervo 
1523e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1524b62f328bSVille Tervo 
1525e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1526e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1527e760ec12SJohan Hedberg 	 */
1528e760ec12SJohan Hedberg 	if (hcon->out)
1529e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1530cc8dba2bSMarcel Holtmann 
153180afeb6cSMarcel Holtmann 	/* For LE slave connections, make sure the connection interval
153280afeb6cSMarcel Holtmann 	 * is in the range of the minium and maximum interval that has
153380afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
153480afeb6cSMarcel Holtmann 	 * the connection update procedure.
153580afeb6cSMarcel Holtmann 	 */
153640bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
153780afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
153880afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
153980afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
154080afeb6cSMarcel Holtmann 
154180afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
154280afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
154380afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
154480afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
154580afeb6cSMarcel Holtmann 
154680afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
154780afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
154880afeb6cSMarcel Holtmann 	}
1549b62f328bSVille Tervo }
1550b62f328bSVille Tervo 
15510a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
15520a708f8fSGustavo F. Padovan {
155348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1554cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
15550a708f8fSGustavo F. Padovan 
15560a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15570a708f8fSGustavo F. Padovan 
1558aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1559aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1560aeaeb4bbSJohan Hedberg 
1561e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1562e760ec12SJohan Hedberg 
15633df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1564baa7e1faSGustavo F. Padovan 
15656be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15660a708f8fSGustavo F. Padovan 
15672338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
1568416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1569416fa752SAndrei Emeltchenko 			continue;
1570416fa752SAndrei Emeltchenko 		}
1571416fa752SAndrei Emeltchenko 
1572cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1573f1496deeSJohan Hedberg 			l2cap_le_start(chan);
157463128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1575aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
157674e75740SGustavo Padovan 				l2cap_chan_ready(chan);
15771c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1578fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15791c244f79SGustavo Padovan 		}
15800a708f8fSGustavo F. Padovan 
15816be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15820a708f8fSGustavo F. Padovan 	}
15830a708f8fSGustavo F. Padovan 
15843df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
158561a939c6SJohan Hedberg 
158679a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
158779a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
158879a05727SJohan Hedberg 
158961a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
15900a708f8fSGustavo F. Padovan }
15910a708f8fSGustavo F. Padovan 
15920a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15930a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15940a708f8fSGustavo F. Padovan {
159548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15960a708f8fSGustavo F. Padovan 
15970a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15980a708f8fSGustavo F. Padovan 
15993df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16000a708f8fSGustavo F. Padovan 
16013df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1602ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
16031d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
16040a708f8fSGustavo F. Padovan 	}
16050a708f8fSGustavo F. Padovan 
16063df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16070a708f8fSGustavo F. Padovan }
16080a708f8fSGustavo F. Padovan 
1609f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
16100a708f8fSGustavo F. Padovan {
1611f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1612030013d8SGustavo F. Padovan 					       info_timer.work);
16130a708f8fSGustavo F. Padovan 
16140a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
16150a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
16160a708f8fSGustavo F. Padovan 
16170a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
16180a708f8fSGustavo F. Padovan }
16190a708f8fSGustavo F. Padovan 
16202c8e1411SDavid Herrmann /*
16212c8e1411SDavid Herrmann  * l2cap_user
16222c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
16232c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
16242c8e1411SDavid Herrmann  * during unregistration.
16252c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
16262c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
16272c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16282c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
16292c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16302c8e1411SDavid Herrmann  * any time if they don't.
16312c8e1411SDavid Herrmann  */
16322c8e1411SDavid Herrmann 
16332c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16342c8e1411SDavid Herrmann {
16352c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16362c8e1411SDavid Herrmann 	int ret;
16372c8e1411SDavid Herrmann 
16382c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
16392c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
16402c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16412c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
16422c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
16432c8e1411SDavid Herrmann 	 * here, too. */
16442c8e1411SDavid Herrmann 
16452c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16462c8e1411SDavid Herrmann 
1647835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
16482c8e1411SDavid Herrmann 		ret = -EINVAL;
16492c8e1411SDavid Herrmann 		goto out_unlock;
16502c8e1411SDavid Herrmann 	}
16512c8e1411SDavid Herrmann 
16522c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
16532c8e1411SDavid Herrmann 	if (!conn->hchan) {
16542c8e1411SDavid Herrmann 		ret = -ENODEV;
16552c8e1411SDavid Herrmann 		goto out_unlock;
16562c8e1411SDavid Herrmann 	}
16572c8e1411SDavid Herrmann 
16582c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
16592c8e1411SDavid Herrmann 	if (ret)
16602c8e1411SDavid Herrmann 		goto out_unlock;
16612c8e1411SDavid Herrmann 
16622c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16632c8e1411SDavid Herrmann 	ret = 0;
16642c8e1411SDavid Herrmann 
16652c8e1411SDavid Herrmann out_unlock:
16662c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16672c8e1411SDavid Herrmann 	return ret;
16682c8e1411SDavid Herrmann }
16692c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16702c8e1411SDavid Herrmann 
16712c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16722c8e1411SDavid Herrmann {
16732c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16742c8e1411SDavid Herrmann 
16752c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16762c8e1411SDavid Herrmann 
1677835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
16782c8e1411SDavid Herrmann 		goto out_unlock;
16792c8e1411SDavid Herrmann 
1680ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
16812c8e1411SDavid Herrmann 	user->remove(conn, user);
16822c8e1411SDavid Herrmann 
16832c8e1411SDavid Herrmann out_unlock:
16842c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16852c8e1411SDavid Herrmann }
16862c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16872c8e1411SDavid Herrmann 
16882c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16892c8e1411SDavid Herrmann {
16902c8e1411SDavid Herrmann 	struct l2cap_user *user;
16912c8e1411SDavid Herrmann 
16922c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16932c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1694ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
16952c8e1411SDavid Herrmann 		user->remove(conn, user);
16962c8e1411SDavid Herrmann 	}
16972c8e1411SDavid Herrmann }
16982c8e1411SDavid Herrmann 
16995d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
17005d3de7dfSVinicius Costa Gomes {
17015d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
17025d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
17035d3de7dfSVinicius Costa Gomes 
17045d3de7dfSVinicius Costa Gomes 	if (!conn)
17055d3de7dfSVinicius Costa Gomes 		return;
17065d3de7dfSVinicius Costa Gomes 
17075d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
17085d3de7dfSVinicius Costa Gomes 
17095d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
17105d3de7dfSVinicius Costa Gomes 
171161a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
17127ab56c3aSJukka Taimisto 
17137ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
17147ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
17157ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
17167ab56c3aSJukka Taimisto 	 */
17177ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
17187ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
171961a939c6SJohan Hedberg 
1720f3d82d0cSJohan Hedberg 	if (work_pending(&conn->id_addr_update_work))
1721f3d82d0cSJohan Hedberg 		cancel_work_sync(&conn->id_addr_update_work);
1722f3d82d0cSJohan Hedberg 
17232c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
17242c8e1411SDavid Herrmann 
1725e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1726e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1727e31fb860SJohan Hedberg 
17283df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17293df91ea2SAndrei Emeltchenko 
17305d3de7dfSVinicius Costa Gomes 	/* Kill channels */
17315d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
173261d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
17336be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17346be36555SAndrei Emeltchenko 
17355d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
17366be36555SAndrei Emeltchenko 
17376be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17386be36555SAndrei Emeltchenko 
173980b98027SGustavo Padovan 		chan->ops->close(chan);
174061d6ef3eSMat Martineau 		l2cap_chan_put(chan);
17415d3de7dfSVinicius Costa Gomes 	}
17425d3de7dfSVinicius Costa Gomes 
17433df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17443df91ea2SAndrei Emeltchenko 
174573d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
174673d80debSLuiz Augusto von Dentz 
17475d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1748127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
17495d3de7dfSVinicius Costa Gomes 
17505d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
17519c903e37SDavid Herrmann 	conn->hchan = NULL;
17529c903e37SDavid Herrmann 	l2cap_conn_put(conn);
17535d3de7dfSVinicius Costa Gomes }
17545d3de7dfSVinicius Costa Gomes 
17559c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17569c903e37SDavid Herrmann {
17579c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17589c903e37SDavid Herrmann 
17599c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17609c903e37SDavid Herrmann 	kfree(conn);
17619c903e37SDavid Herrmann }
17629c903e37SDavid Herrmann 
176351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
17649c903e37SDavid Herrmann {
17659c903e37SDavid Herrmann 	kref_get(&conn->ref);
176651bb8457SJohan Hedberg 	return conn;
17679c903e37SDavid Herrmann }
17689c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
17699c903e37SDavid Herrmann 
17709c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
17719c903e37SDavid Herrmann {
17729c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
17739c903e37SDavid Herrmann }
17749c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
17759c903e37SDavid Herrmann 
17760a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
17770a708f8fSGustavo F. Padovan 
1778c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
17790a708f8fSGustavo F. Padovan  * Returns closest match.
17800a708f8fSGustavo F. Padovan  */
1781c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1782c2287681SIdo Yariv 						   bdaddr_t *src,
1783bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1784bf20fd4eSJohan Hedberg 						   u8 link_type)
17850a708f8fSGustavo F. Padovan {
178623691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
17870a708f8fSGustavo F. Padovan 
178823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
17890a708f8fSGustavo F. Padovan 
179023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
179189bc500eSGustavo F. Padovan 		if (state && c->state != state)
17920a708f8fSGustavo F. Padovan 			continue;
17930a708f8fSGustavo F. Padovan 
1794bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1795bf20fd4eSJohan Hedberg 			continue;
1796bf20fd4eSJohan Hedberg 
1797bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1798bf20fd4eSJohan Hedberg 			continue;
1799bf20fd4eSJohan Hedberg 
180023691d75SGustavo F. Padovan 		if (c->psm == psm) {
1801c2287681SIdo Yariv 			int src_match, dst_match;
1802c2287681SIdo Yariv 			int src_any, dst_any;
1803c2287681SIdo Yariv 
18040a708f8fSGustavo F. Padovan 			/* Exact match. */
18057eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18067eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1807c2287681SIdo Yariv 			if (src_match && dst_match) {
1808a24cce14SJohan Hedberg 				l2cap_chan_hold(c);
1809a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
181023691d75SGustavo F. Padovan 				return c;
181123691d75SGustavo F. Padovan 			}
18120a708f8fSGustavo F. Padovan 
18130a708f8fSGustavo F. Padovan 			/* Closest match */
18147eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18157eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1816c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1817c2287681SIdo Yariv 			    (src_any && dst_any))
181823691d75SGustavo F. Padovan 				c1 = c;
18190a708f8fSGustavo F. Padovan 		}
18200a708f8fSGustavo F. Padovan 	}
18210a708f8fSGustavo F. Padovan 
1822a24cce14SJohan Hedberg 	if (c1)
1823a24cce14SJohan Hedberg 		l2cap_chan_hold(c1);
1824a24cce14SJohan Hedberg 
182523691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18260a708f8fSGustavo F. Padovan 
182723691d75SGustavo F. Padovan 	return c1;
18280a708f8fSGustavo F. Padovan }
18290a708f8fSGustavo F. Padovan 
1830721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
18310a708f8fSGustavo F. Padovan {
1832721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1833721c4181SGustavo F. Padovan 					       monitor_timer.work);
18340a708f8fSGustavo F. Padovan 
1835525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
18360a708f8fSGustavo F. Padovan 
18376be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
18386be36555SAndrei Emeltchenko 
183980909e04SMat Martineau 	if (!chan->conn) {
18406be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
18418d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
18420a708f8fSGustavo F. Padovan 		return;
18430a708f8fSGustavo F. Padovan 	}
18440a708f8fSGustavo F. Padovan 
1845401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
18460a708f8fSGustavo F. Padovan 
18476be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
18488d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
18490a708f8fSGustavo F. Padovan }
18500a708f8fSGustavo F. Padovan 
1851721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
18520a708f8fSGustavo F. Padovan {
1853721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1854721c4181SGustavo F. Padovan 					       retrans_timer.work);
18550a708f8fSGustavo F. Padovan 
185649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
18570a708f8fSGustavo F. Padovan 
18586be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
18596be36555SAndrei Emeltchenko 
186080909e04SMat Martineau 	if (!chan->conn) {
186180909e04SMat Martineau 		l2cap_chan_unlock(chan);
186280909e04SMat Martineau 		l2cap_chan_put(chan);
186380909e04SMat Martineau 		return;
186480909e04SMat Martineau 	}
18650a708f8fSGustavo F. Padovan 
1866401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
18676be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
18688d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
18690a708f8fSGustavo F. Padovan }
18700a708f8fSGustavo F. Padovan 
1871d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
18723733937dSMat Martineau 				 struct sk_buff_head *skbs)
18730a708f8fSGustavo F. Padovan {
18740a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
18753733937dSMat Martineau 	struct l2cap_ctrl *control;
18760a708f8fSGustavo F. Padovan 
18773733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
18783733937dSMat Martineau 
1879b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1880b99e13adSMat Martineau 		return;
1881b99e13adSMat Martineau 
18823733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
18833733937dSMat Martineau 
18843733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
18853733937dSMat Martineau 
18863733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
18873733937dSMat Martineau 
1888a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1889a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
18903733937dSMat Martineau 
18913733937dSMat Martineau 		control->reqseq = 0;
18923733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
18933733937dSMat Martineau 
18943733937dSMat Martineau 		__pack_control(chan, control, skb);
18950a708f8fSGustavo F. Padovan 
189647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
18973733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
18983733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
18990a708f8fSGustavo F. Padovan 		}
19000a708f8fSGustavo F. Padovan 
19014343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
19020a708f8fSGustavo F. Padovan 
1903b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
19043733937dSMat Martineau 
1905836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
19063733937dSMat Martineau 		chan->frames_sent++;
19070a708f8fSGustavo F. Padovan 	}
19080a708f8fSGustavo F. Padovan }
19090a708f8fSGustavo F. Padovan 
191067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
19110a708f8fSGustavo F. Padovan {
19120a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
191318a48e76SMat Martineau 	struct l2cap_ctrl *control;
191418a48e76SMat Martineau 	int sent = 0;
191518a48e76SMat Martineau 
191618a48e76SMat Martineau 	BT_DBG("chan %p", chan);
19170a708f8fSGustavo F. Padovan 
191889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
19190a708f8fSGustavo F. Padovan 		return -ENOTCONN;
19200a708f8fSGustavo F. Padovan 
192194122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
192294122bbeSMat Martineau 		return 0;
192394122bbeSMat Martineau 
1924b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1925b99e13adSMat Martineau 		return 0;
1926b99e13adSMat Martineau 
192718a48e76SMat Martineau 	while (chan->tx_send_head &&
192818a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
192918a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
19300a708f8fSGustavo F. Padovan 
193118a48e76SMat Martineau 		skb = chan->tx_send_head;
19320a708f8fSGustavo F. Padovan 
1933a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1934a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
19350a708f8fSGustavo F. Padovan 
1936e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
193718a48e76SMat Martineau 			control->final = 1;
1938e2ab4353SGustavo F. Padovan 
193918a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
194018a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
194118a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
19420a708f8fSGustavo F. Padovan 
194318a48e76SMat Martineau 		__pack_control(chan, control, skb);
19440a708f8fSGustavo F. Padovan 
194547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
194618a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
194718a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19480a708f8fSGustavo F. Padovan 		}
19490a708f8fSGustavo F. Padovan 
195018a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
195118a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
195218a48e76SMat Martineau 		 */
195318a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
195418a48e76SMat Martineau 
195518a48e76SMat Martineau 		if (!tx_skb)
195618a48e76SMat Martineau 			break;
19570a708f8fSGustavo F. Padovan 
19581a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
19590a708f8fSGustavo F. Padovan 
1960836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
19616a026610SGustavo F. Padovan 		chan->unacked_frames++;
19626a026610SGustavo F. Padovan 		chan->frames_sent++;
196318a48e76SMat Martineau 		sent++;
19640a708f8fSGustavo F. Padovan 
196558d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
196658d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
19670a708f8fSGustavo F. Padovan 		else
196858d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
196918a48e76SMat Martineau 
197018a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
1971b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
19720a708f8fSGustavo F. Padovan 	}
19730a708f8fSGustavo F. Padovan 
1974b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
1975b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
197618a48e76SMat Martineau 
197718a48e76SMat Martineau 	return sent;
19780a708f8fSGustavo F. Padovan }
19790a708f8fSGustavo F. Padovan 
1980e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1981e1fbd4c1SMat Martineau {
1982e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1983e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1984e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1985e1fbd4c1SMat Martineau 	u16 seq;
1986e1fbd4c1SMat Martineau 
1987e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1988e1fbd4c1SMat Martineau 
1989e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1990e1fbd4c1SMat Martineau 		return;
1991e1fbd4c1SMat Martineau 
1992b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1993b99e13adSMat Martineau 		return;
1994b99e13adSMat Martineau 
1995e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1996e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1997e1fbd4c1SMat Martineau 
1998e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1999e1fbd4c1SMat Martineau 		if (!skb) {
2000e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2001e1fbd4c1SMat Martineau 			       seq);
2002e1fbd4c1SMat Martineau 			continue;
2003e1fbd4c1SMat Martineau 		}
2004e1fbd4c1SMat Martineau 
2005a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
2006a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
2007e1fbd4c1SMat Martineau 
2008e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2009a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2010e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
20115e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2012e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2013e1fbd4c1SMat Martineau 			break;
2014e1fbd4c1SMat Martineau 		}
2015e1fbd4c1SMat Martineau 
2016e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2017e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2018e1fbd4c1SMat Martineau 			control.final = 1;
2019e1fbd4c1SMat Martineau 		else
2020e1fbd4c1SMat Martineau 			control.final = 0;
2021e1fbd4c1SMat Martineau 
2022e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2023e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2024e1fbd4c1SMat Martineau 			 * writeable copy
2025e1fbd4c1SMat Martineau 			 */
20268bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2027e1fbd4c1SMat Martineau 		} else {
20288bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2029e1fbd4c1SMat Martineau 		}
2030e1fbd4c1SMat Martineau 
2031e1fbd4c1SMat Martineau 		if (!tx_skb) {
2032e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2033e1fbd4c1SMat Martineau 			break;
2034e1fbd4c1SMat Martineau 		}
2035e1fbd4c1SMat Martineau 
2036e1fbd4c1SMat Martineau 		/* Update skb contents */
2037e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2038e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2039e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2040e1fbd4c1SMat Martineau 		} else {
2041e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2042e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2043e1fbd4c1SMat Martineau 		}
2044e1fbd4c1SMat Martineau 
204513cac152SLukasz Rymanowski 		/* Update FCS */
2046e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
204713cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
204813cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
204913cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
205013cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2051e1fbd4c1SMat Martineau 		}
2052e1fbd4c1SMat Martineau 
2053e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2054e1fbd4c1SMat Martineau 
2055e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2056e1fbd4c1SMat Martineau 
2057e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2058e1fbd4c1SMat Martineau 	}
2059e1fbd4c1SMat Martineau }
2060e1fbd4c1SMat Martineau 
2061f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2062f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2063f80842a8SMat Martineau {
2064f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2065f80842a8SMat Martineau 
2066f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2067f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2068f80842a8SMat Martineau }
2069f80842a8SMat Martineau 
2070d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2071d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2072d2a7ac5dSMat Martineau {
2073e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2074e1fbd4c1SMat Martineau 
2075e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2076e1fbd4c1SMat Martineau 
2077e1fbd4c1SMat Martineau 	if (control->poll)
2078e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2079e1fbd4c1SMat Martineau 
2080e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2081e1fbd4c1SMat Martineau 
2082e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2083e1fbd4c1SMat Martineau 		return;
2084e1fbd4c1SMat Martineau 
2085e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2086e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2087a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2088e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2089e1fbd4c1SMat Martineau 				break;
2090e1fbd4c1SMat Martineau 		}
2091e1fbd4c1SMat Martineau 
2092e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2093e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2094e1fbd4c1SMat Martineau 				break;
2095e1fbd4c1SMat Martineau 
2096e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2097a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2098e1fbd4c1SMat Martineau 		}
2099e1fbd4c1SMat Martineau 
2100e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2101e1fbd4c1SMat Martineau 	}
2102d2a7ac5dSMat Martineau }
2103d2a7ac5dSMat Martineau 
2104b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2105b17e73bbSSzymon Janc {
21060a0aba42SMat Martineau 	struct l2cap_ctrl control;
21070a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
21080a0aba42SMat Martineau 					 chan->last_acked_seq);
21090a0aba42SMat Martineau 	int threshold;
21100a0aba42SMat Martineau 
21110a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
21120a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
21130a0aba42SMat Martineau 
21140a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
21150a0aba42SMat Martineau 	control.sframe = 1;
21160a0aba42SMat Martineau 
21170a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
21180a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2119b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
21200a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
21210a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
21220a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
21230a0aba42SMat Martineau 	} else {
21240a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
21250a0aba42SMat Martineau 			l2cap_ertm_send(chan);
21260a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
21270a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
21280a0aba42SMat Martineau 				frames_to_ack = 0;
21290a0aba42SMat Martineau 		}
21300a0aba42SMat Martineau 
2131c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
21320a0aba42SMat Martineau 		 * Calculate without mul or div
21330a0aba42SMat Martineau 		 */
2134c20f8e35SMat Martineau 		threshold = chan->ack_win;
21350a0aba42SMat Martineau 		threshold += threshold << 1;
21360a0aba42SMat Martineau 		threshold >>= 2;
21370a0aba42SMat Martineau 
2138b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
21390a0aba42SMat Martineau 		       threshold);
21400a0aba42SMat Martineau 
21410a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
21420a0aba42SMat Martineau 			__clear_ack_timer(chan);
21430a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
21440a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
21450a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
21460a0aba42SMat Martineau 			frames_to_ack = 0;
21470a0aba42SMat Martineau 		}
21480a0aba42SMat Martineau 
21490a0aba42SMat Martineau 		if (frames_to_ack)
21500a0aba42SMat Martineau 			__set_ack_timer(chan);
21510a0aba42SMat Martineau 	}
2152b17e73bbSSzymon Janc }
2153b17e73bbSSzymon Janc 
215404124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
215504124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
215604124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
21570a708f8fSGustavo F. Padovan {
21580952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
21590a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
216090338947SGustavo Padovan 	int sent = 0;
21610a708f8fSGustavo F. Padovan 
2162cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
21630a708f8fSGustavo F. Padovan 		return -EFAULT;
21640a708f8fSGustavo F. Padovan 
21650a708f8fSGustavo F. Padovan 	sent += count;
21660a708f8fSGustavo F. Padovan 	len  -= count;
21670a708f8fSGustavo F. Padovan 
21680a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
21690a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
21700a708f8fSGustavo F. Padovan 	while (len) {
2171fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2172fbe00700SGustavo Padovan 
21730a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
21740a708f8fSGustavo F. Padovan 
2175d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
217690338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2177fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2178fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
21792f7719ceSAndrei Emeltchenko 
2180fbe00700SGustavo Padovan 		*frag = tmp;
2181fbe00700SGustavo Padovan 
2182cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2183cbbd26b8SAl Viro 				   &msg->msg_iter))
21840a708f8fSGustavo F. Padovan 			return -EFAULT;
21850a708f8fSGustavo F. Padovan 
21860a708f8fSGustavo F. Padovan 		sent += count;
21870a708f8fSGustavo F. Padovan 		len  -= count;
21880a708f8fSGustavo F. Padovan 
21892d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
21902d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
21912d0ed3d5SGustavo Padovan 
21920a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
21930a708f8fSGustavo F. Padovan 	}
21940a708f8fSGustavo F. Padovan 
21950a708f8fSGustavo F. Padovan 	return sent;
21960a708f8fSGustavo F. Padovan }
21970a708f8fSGustavo F. Padovan 
21985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
21998d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
22000a708f8fSGustavo F. Padovan {
22018c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22020a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
220303a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
22040a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22050a708f8fSGustavo F. Padovan 
22068d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
22078d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
22080a708f8fSGustavo F. Padovan 
22090a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
22102f7719ceSAndrei Emeltchenko 
2211d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
221290338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
221390338947SGustavo Padovan 	if (IS_ERR(skb))
221490338947SGustavo Padovan 		return skb;
22150a708f8fSGustavo F. Padovan 
22160a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22174df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2218fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2219daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
222043b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
22210a708f8fSGustavo F. Padovan 
22220952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22230a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22240a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22250a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22260a708f8fSGustavo F. Padovan 	}
22270a708f8fSGustavo F. Padovan 	return skb;
22280a708f8fSGustavo F. Padovan }
22290a708f8fSGustavo F. Padovan 
22305e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
22318d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
22320a708f8fSGustavo F. Padovan {
22338c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22340a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2235f2ba7faeSGustavo Padovan 	int err, count;
22360a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22370a708f8fSGustavo F. Padovan 
2238b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
22390a708f8fSGustavo F. Padovan 
2240f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
22412f7719ceSAndrei Emeltchenko 
2242d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
224390338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
224490338947SGustavo Padovan 	if (IS_ERR(skb))
224590338947SGustavo Padovan 		return skb;
22460a708f8fSGustavo F. Padovan 
22470a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22484df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2249fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
22506ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
22510a708f8fSGustavo F. Padovan 
22520952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22530a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22540a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22550a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22560a708f8fSGustavo F. Padovan 	}
22570a708f8fSGustavo F. Padovan 	return skb;
22580a708f8fSGustavo F. Padovan }
22590a708f8fSGustavo F. Padovan 
2260ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2261ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
226294122bbeSMat Martineau 					       u16 sdulen)
22630a708f8fSGustavo F. Padovan {
22648c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22650a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2266e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
22670a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22680a708f8fSGustavo F. Padovan 
2269b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
22700a708f8fSGustavo F. Padovan 
22710a708f8fSGustavo F. Padovan 	if (!conn)
22720a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
22730a708f8fSGustavo F. Padovan 
2274ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2275e4ca6d98SAndrei Emeltchenko 
22760a708f8fSGustavo F. Padovan 	if (sdulen)
227703a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
22780a708f8fSGustavo F. Padovan 
227947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
228003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
22810a708f8fSGustavo F. Padovan 
22820a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
22832f7719ceSAndrei Emeltchenko 
2284d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
228590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
228690338947SGustavo Padovan 	if (IS_ERR(skb))
228790338947SGustavo Padovan 		return skb;
22880a708f8fSGustavo F. Padovan 
22890a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22904df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2291fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
22920a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
229388843ab0SAndrei Emeltchenko 
229418a48e76SMat Martineau 	/* Control header is populated later */
229518a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
229618a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
229718a48e76SMat Martineau 	else
229818a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
229988843ab0SAndrei Emeltchenko 
23000a708f8fSGustavo F. Padovan 	if (sdulen)
230103a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
23020a708f8fSGustavo F. Padovan 
23030952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23040a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23050a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23060a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23070a708f8fSGustavo F. Padovan 	}
23080a708f8fSGustavo F. Padovan 
2309a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2310a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
23110a708f8fSGustavo F. Padovan 	return skb;
23120a708f8fSGustavo F. Padovan }
23130a708f8fSGustavo F. Padovan 
231494122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
231594122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
231694122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
23170a708f8fSGustavo F. Padovan {
23180a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
231994122bbeSMat Martineau 	u16 sdu_len;
232094122bbeSMat Martineau 	size_t pdu_len;
232194122bbeSMat Martineau 	u8 sar;
23220a708f8fSGustavo F. Padovan 
2323b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
23240a708f8fSGustavo F. Padovan 
232594122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
232694122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
232794122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
232894122bbeSMat Martineau 	 */
232994122bbeSMat Martineau 
233094122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
233194122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
233294122bbeSMat Martineau 
2333a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2334a549574dSMat Martineau 	if (!chan->hs_hcon)
233594122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
233694122bbeSMat Martineau 
233794122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
233835d401dfSGustavo Padovan 	if (chan->fcs)
233935d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
234035d401dfSGustavo Padovan 
2341ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
234294122bbeSMat Martineau 
234394122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
234494122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
234594122bbeSMat Martineau 
234694122bbeSMat Martineau 	if (len <= pdu_len) {
234794122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
234894122bbeSMat Martineau 		sdu_len = 0;
234994122bbeSMat Martineau 		pdu_len = len;
235094122bbeSMat Martineau 	} else {
235194122bbeSMat Martineau 		sar = L2CAP_SAR_START;
235294122bbeSMat Martineau 		sdu_len = len;
235394122bbeSMat Martineau 	}
23540a708f8fSGustavo F. Padovan 
23550a708f8fSGustavo F. Padovan 	while (len > 0) {
235694122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
23570a708f8fSGustavo F. Padovan 
23580a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
235994122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
23600a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
23610a708f8fSGustavo F. Padovan 		}
23620a708f8fSGustavo F. Padovan 
2363a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
236494122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
23650a708f8fSGustavo F. Padovan 
236694122bbeSMat Martineau 		len -= pdu_len;
2367069cb270SLukasz Rymanowski 		if (sdu_len)
236894122bbeSMat Martineau 			sdu_len = 0;
236994122bbeSMat Martineau 
237094122bbeSMat Martineau 		if (len <= pdu_len) {
237194122bbeSMat Martineau 			sar = L2CAP_SAR_END;
237294122bbeSMat Martineau 			pdu_len = len;
237394122bbeSMat Martineau 		} else {
237494122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
237594122bbeSMat Martineau 		}
237694122bbeSMat Martineau 	}
237794122bbeSMat Martineau 
2378f0f62799SGustavo Padovan 	return 0;
23790a708f8fSGustavo F. Padovan }
23800a708f8fSGustavo F. Padovan 
2381177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2382177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2383177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2384177f8f2bSJohan Hedberg {
2385177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2386177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2387177f8f2bSJohan Hedberg 	int err, count, hlen;
2388177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2389177f8f2bSJohan Hedberg 
2390177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2391177f8f2bSJohan Hedberg 
2392177f8f2bSJohan Hedberg 	if (!conn)
2393177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2394177f8f2bSJohan Hedberg 
2395177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2396177f8f2bSJohan Hedberg 
2397177f8f2bSJohan Hedberg 	if (sdulen)
2398177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2399177f8f2bSJohan Hedberg 
2400177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2401177f8f2bSJohan Hedberg 
2402d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2403177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2404177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2405177f8f2bSJohan Hedberg 		return skb;
2406177f8f2bSJohan Hedberg 
2407177f8f2bSJohan Hedberg 	/* Create L2CAP header */
24084df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2409177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2410177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2411177f8f2bSJohan Hedberg 
2412177f8f2bSJohan Hedberg 	if (sdulen)
2413177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2414177f8f2bSJohan Hedberg 
2415177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2416177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2417177f8f2bSJohan Hedberg 		kfree_skb(skb);
2418177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2419177f8f2bSJohan Hedberg 	}
2420177f8f2bSJohan Hedberg 
2421177f8f2bSJohan Hedberg 	return skb;
2422177f8f2bSJohan Hedberg }
2423177f8f2bSJohan Hedberg 
2424177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2425177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2426177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2427177f8f2bSJohan Hedberg {
2428177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2429177f8f2bSJohan Hedberg 	size_t pdu_len;
2430177f8f2bSJohan Hedberg 	u16 sdu_len;
2431177f8f2bSJohan Hedberg 
2432177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2433177f8f2bSJohan Hedberg 
2434177f8f2bSJohan Hedberg 	sdu_len = len;
243572c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2436177f8f2bSJohan Hedberg 
2437177f8f2bSJohan Hedberg 	while (len > 0) {
2438177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2439177f8f2bSJohan Hedberg 			pdu_len = len;
2440177f8f2bSJohan Hedberg 
2441177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2442177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2443177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2444177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2445177f8f2bSJohan Hedberg 		}
2446177f8f2bSJohan Hedberg 
2447177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2448177f8f2bSJohan Hedberg 
2449177f8f2bSJohan Hedberg 		len -= pdu_len;
2450177f8f2bSJohan Hedberg 
2451177f8f2bSJohan Hedberg 		if (sdu_len) {
2452177f8f2bSJohan Hedberg 			sdu_len = 0;
2453177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2454177f8f2bSJohan Hedberg 		}
2455177f8f2bSJohan Hedberg 	}
2456177f8f2bSJohan Hedberg 
2457177f8f2bSJohan Hedberg 	return 0;
2458177f8f2bSJohan Hedberg }
2459177f8f2bSJohan Hedberg 
24608a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
24618a505b7fSLuiz Augusto von Dentz {
24628a505b7fSLuiz Augusto von Dentz 	int sent = 0;
24638a505b7fSLuiz Augusto von Dentz 
24648a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
24658a505b7fSLuiz Augusto von Dentz 
24668a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
24678a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
24688a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
24698a505b7fSLuiz Augusto von Dentz 		sent++;
24708a505b7fSLuiz Augusto von Dentz 	}
24718a505b7fSLuiz Augusto von Dentz 
24728a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
24738a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
24748a505b7fSLuiz Augusto von Dentz }
24758a505b7fSLuiz Augusto von Dentz 
24768d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
24779a91a04aSGustavo F. Padovan {
24789a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
24799a91a04aSGustavo F. Padovan 	int err;
248094122bbeSMat Martineau 	struct sk_buff_head seg_queue;
24819a91a04aSGustavo F. Padovan 
248231e8ce80SSeung-Woo Kim 	if (!chan->conn)
248331e8ce80SSeung-Woo Kim 		return -ENOTCONN;
248431e8ce80SSeung-Woo Kim 
24859a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2486715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
24878d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
24889a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
24899a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
24909a91a04aSGustavo F. Padovan 
2491ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2492ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2493ede81a2aSAndrzej Kaczmarek 		 */
2494ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2495ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2496ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2497ede81a2aSAndrzej Kaczmarek 		}
2498ede81a2aSAndrzej Kaczmarek 
24999a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25009a91a04aSGustavo F. Padovan 		return len;
25019a91a04aSGustavo F. Padovan 	}
25029a91a04aSGustavo F. Padovan 
25039a91a04aSGustavo F. Padovan 	switch (chan->mode) {
250438319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
2505177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2506177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2507177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2508177f8f2bSJohan Hedberg 
2509177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2510177f8f2bSJohan Hedberg 
2511177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2512177f8f2bSJohan Hedberg 
2513177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2514177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2515177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2516177f8f2bSJohan Hedberg 		}
2517177f8f2bSJohan Hedberg 
2518177f8f2bSJohan Hedberg 		if (err)
2519177f8f2bSJohan Hedberg 			return err;
2520177f8f2bSJohan Hedberg 
2521177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2522177f8f2bSJohan Hedberg 
25238a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2524177f8f2bSJohan Hedberg 
2525177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2526177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2527177f8f2bSJohan Hedberg 
2528177f8f2bSJohan Hedberg 		err = len;
2529177f8f2bSJohan Hedberg 
2530177f8f2bSJohan Hedberg 		break;
2531177f8f2bSJohan Hedberg 
2532fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
25339a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
25349a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
25359a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
25369a91a04aSGustavo F. Padovan 
25379a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
25388d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
25399a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25409a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25419a91a04aSGustavo F. Padovan 
2542ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2543ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2544ede81a2aSAndrzej Kaczmarek 		 */
2545ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2546ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2547ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2548ede81a2aSAndrzej Kaczmarek 		}
2549ede81a2aSAndrzej Kaczmarek 
25509a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25519a91a04aSGustavo F. Padovan 		err = len;
25529a91a04aSGustavo F. Padovan 		break;
25539a91a04aSGustavo F. Padovan 
25549a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
25559a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
255694122bbeSMat Martineau 		/* Check outgoing MTU */
255794122bbeSMat Martineau 		if (len > chan->omtu) {
255894122bbeSMat Martineau 			err = -EMSGSIZE;
25599a91a04aSGustavo F. Padovan 			break;
25609a91a04aSGustavo F. Padovan 		}
25619a91a04aSGustavo F. Padovan 
256294122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
256394122bbeSMat Martineau 
256494122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
256594122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
256694122bbeSMat Martineau 		 * allocation.
256794122bbeSMat Martineau 		 */
256894122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
256994122bbeSMat Martineau 
257094122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
257194122bbeSMat Martineau 		 * check that it is still connected.
257294122bbeSMat Martineau 		 */
257394122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
257494122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
257594122bbeSMat Martineau 			err = -ENOTCONN;
25769a91a04aSGustavo F. Padovan 		}
25779a91a04aSGustavo F. Padovan 
257894122bbeSMat Martineau 		if (err)
257994122bbeSMat Martineau 			break;
258094122bbeSMat Martineau 
25813733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2582d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
25833733937dSMat Martineau 		else
2584d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
258594122bbeSMat Martineau 
25869a91a04aSGustavo F. Padovan 		err = len;
25879a91a04aSGustavo F. Padovan 
258894122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
258994122bbeSMat Martineau 		 * seg_queue and need to be purged.
259094122bbeSMat Martineau 		 */
259194122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
25929a91a04aSGustavo F. Padovan 		break;
25939a91a04aSGustavo F. Padovan 
25949a91a04aSGustavo F. Padovan 	default:
25959a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
25969a91a04aSGustavo F. Padovan 		err = -EBADFD;
25979a91a04aSGustavo F. Padovan 	}
25989a91a04aSGustavo F. Padovan 
25999a91a04aSGustavo F. Padovan 	return err;
26009a91a04aSGustavo F. Padovan }
26016b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
26029a91a04aSGustavo F. Padovan 
2603d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2604d2a7ac5dSMat Martineau {
2605bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2606bed68bdeSMat Martineau 	u16 seq;
2607bed68bdeSMat Martineau 
2608b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2609bed68bdeSMat Martineau 
2610bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2611bed68bdeSMat Martineau 	control.sframe = 1;
2612bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2613bed68bdeSMat Martineau 
2614bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2615bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2616bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2617bed68bdeSMat Martineau 			control.reqseq = seq;
2618bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2619bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2620bed68bdeSMat Martineau 		}
2621bed68bdeSMat Martineau 	}
2622bed68bdeSMat Martineau 
2623bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2624d2a7ac5dSMat Martineau }
2625d2a7ac5dSMat Martineau 
2626d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2627d2a7ac5dSMat Martineau {
2628bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2629bed68bdeSMat Martineau 
2630bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2631bed68bdeSMat Martineau 
2632bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2633bed68bdeSMat Martineau 		return;
2634bed68bdeSMat Martineau 
2635bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2636bed68bdeSMat Martineau 	control.sframe = 1;
2637bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2638bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2639bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2640d2a7ac5dSMat Martineau }
2641d2a7ac5dSMat Martineau 
2642d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2643d2a7ac5dSMat Martineau {
2644bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2645bed68bdeSMat Martineau 	u16 initial_head;
2646bed68bdeSMat Martineau 	u16 seq;
2647bed68bdeSMat Martineau 
2648b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2649bed68bdeSMat Martineau 
2650bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2651bed68bdeSMat Martineau 	control.sframe = 1;
2652bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2653bed68bdeSMat Martineau 
2654bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2655bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2656bed68bdeSMat Martineau 
2657bed68bdeSMat Martineau 	do {
2658bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2659bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2660bed68bdeSMat Martineau 			break;
2661bed68bdeSMat Martineau 
2662bed68bdeSMat Martineau 		control.reqseq = seq;
2663bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2664bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2665bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2666d2a7ac5dSMat Martineau }
2667d2a7ac5dSMat Martineau 
2668608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2669608bcc6dSMat Martineau {
2670608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2671608bcc6dSMat Martineau 	u16 ackseq;
2672608bcc6dSMat Martineau 
2673b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2674608bcc6dSMat Martineau 
2675608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2676608bcc6dSMat Martineau 		return;
2677608bcc6dSMat Martineau 
2678b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2679608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2680608bcc6dSMat Martineau 
2681608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2682608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2683608bcc6dSMat Martineau 
2684608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2685608bcc6dSMat Martineau 		if (acked_skb) {
2686608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2687608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2688608bcc6dSMat Martineau 			chan->unacked_frames--;
2689608bcc6dSMat Martineau 		}
2690608bcc6dSMat Martineau 	}
2691608bcc6dSMat Martineau 
2692608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2693608bcc6dSMat Martineau 
2694608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2695608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2696608bcc6dSMat Martineau 
2697b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2698608bcc6dSMat Martineau }
2699608bcc6dSMat Martineau 
2700608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2701608bcc6dSMat Martineau {
2702608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2703608bcc6dSMat Martineau 
2704608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2705608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2706608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2707608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2708608bcc6dSMat Martineau }
2709608bcc6dSMat Martineau 
2710d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2711608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2712608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2713608bcc6dSMat Martineau {
2714608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2715608bcc6dSMat Martineau 	       event);
2716608bcc6dSMat Martineau 
2717608bcc6dSMat Martineau 	switch (event) {
2718608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2719608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2720608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2721608bcc6dSMat Martineau 
2722608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2723608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2724608bcc6dSMat Martineau 		break;
2725608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2726608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2727608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2728608bcc6dSMat Martineau 
2729608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2730608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2731608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2732608bcc6dSMat Martineau 			 */
2733608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2734608bcc6dSMat Martineau 		}
2735608bcc6dSMat Martineau 
2736608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2737608bcc6dSMat Martineau 
2738608bcc6dSMat Martineau 		break;
2739608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2740608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2741608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2742608bcc6dSMat Martineau 
2743608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2744608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2745608bcc6dSMat Martineau 
2746608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2747608bcc6dSMat Martineau 			local_control.sframe = 1;
2748608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2749608bcc6dSMat Martineau 			local_control.poll = 1;
2750608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2751a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2752608bcc6dSMat Martineau 
2753608bcc6dSMat Martineau 			chan->retry_count = 1;
2754608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2755608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2756608bcc6dSMat Martineau 		}
2757608bcc6dSMat Martineau 		break;
2758608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2759608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2760608bcc6dSMat Martineau 		break;
2761608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2762608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2763608bcc6dSMat Martineau 		chan->retry_count = 1;
2764608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2765608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2766608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2767608bcc6dSMat Martineau 		break;
2768608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2769608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2770608bcc6dSMat Martineau 		chan->retry_count = 1;
2771608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2772608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2773608bcc6dSMat Martineau 		break;
2774608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2775608bcc6dSMat Martineau 		/* Nothing to process */
2776608bcc6dSMat Martineau 		break;
2777608bcc6dSMat Martineau 	default:
2778608bcc6dSMat Martineau 		break;
2779608bcc6dSMat Martineau 	}
2780608bcc6dSMat Martineau }
2781608bcc6dSMat Martineau 
2782d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2783608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2784608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2785608bcc6dSMat Martineau {
2786608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2787608bcc6dSMat Martineau 	       event);
2788608bcc6dSMat Martineau 
2789608bcc6dSMat Martineau 	switch (event) {
2790608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2791608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2792608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2793608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2794608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2795608bcc6dSMat Martineau 		break;
2796608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2797608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2798608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2799608bcc6dSMat Martineau 
2800608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2801608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2802608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2803608bcc6dSMat Martineau 			 */
2804608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2805608bcc6dSMat Martineau 		}
2806608bcc6dSMat Martineau 
2807608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2808608bcc6dSMat Martineau 
2809608bcc6dSMat Martineau 		break;
2810608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2811608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2812608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2813608bcc6dSMat Martineau 
2814608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2815608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2816608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2817608bcc6dSMat Martineau 			local_control.sframe = 1;
2818608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2819608bcc6dSMat Martineau 			local_control.poll = 1;
2820608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2821a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2822608bcc6dSMat Martineau 
2823608bcc6dSMat Martineau 			chan->retry_count = 1;
2824608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2825608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2826608bcc6dSMat Martineau 		}
2827608bcc6dSMat Martineau 		break;
2828608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2829608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2830608bcc6dSMat Martineau 
2831608bcc6dSMat Martineau 		/* Fall through */
2832608bcc6dSMat Martineau 
2833608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2834608bcc6dSMat Martineau 		if (control && control->final) {
2835608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2836608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2837608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2838608bcc6dSMat Martineau 			chan->retry_count = 0;
2839608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2840608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2841608bcc6dSMat Martineau 		}
2842608bcc6dSMat Martineau 		break;
2843608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2844608bcc6dSMat Martineau 		/* Ignore */
2845608bcc6dSMat Martineau 		break;
2846608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2847608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2848608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2849608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2850608bcc6dSMat Martineau 			chan->retry_count++;
2851608bcc6dSMat Martineau 		} else {
28525e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
2853608bcc6dSMat Martineau 		}
2854608bcc6dSMat Martineau 		break;
2855608bcc6dSMat Martineau 	default:
2856608bcc6dSMat Martineau 		break;
2857608bcc6dSMat Martineau 	}
2858608bcc6dSMat Martineau }
2859608bcc6dSMat Martineau 
2860d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2861608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2862608bcc6dSMat Martineau {
2863608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2864608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2865608bcc6dSMat Martineau 
2866608bcc6dSMat Martineau 	switch (chan->tx_state) {
2867608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2868d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2869608bcc6dSMat Martineau 		break;
2870608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2871d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2872608bcc6dSMat Martineau 		break;
2873608bcc6dSMat Martineau 	default:
2874608bcc6dSMat Martineau 		/* Ignore event */
2875608bcc6dSMat Martineau 		break;
2876608bcc6dSMat Martineau 	}
2877608bcc6dSMat Martineau }
2878608bcc6dSMat Martineau 
28794b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
28804b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
28814b51dae9SMat Martineau {
28824b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2883401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
28844b51dae9SMat Martineau }
28854b51dae9SMat Martineau 
2886f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2887f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2888f80842a8SMat Martineau {
2889f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2890401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2891f80842a8SMat Martineau }
2892f80842a8SMat Martineau 
28930a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
28940a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
28950a708f8fSGustavo F. Padovan {
28960a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
289748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
28980a708f8fSGustavo F. Padovan 
28990a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
29000a708f8fSGustavo F. Padovan 
29013df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
29023d57dc68SGustavo F. Padovan 
29033df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
2904715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
29050a708f8fSGustavo F. Padovan 			continue;
29060a708f8fSGustavo F. Padovan 
29077f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
2908a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
29090a708f8fSGustavo F. Padovan 			continue;
29107f5396a7SGustavo Padovan 
29118bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
29120a708f8fSGustavo F. Padovan 		if (!nskb)
29130a708f8fSGustavo F. Padovan 			continue;
291480b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
29150a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
29160a708f8fSGustavo F. Padovan 	}
29173d57dc68SGustavo F. Padovan 
29183df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
29190a708f8fSGustavo F. Padovan }
29200a708f8fSGustavo F. Padovan 
29210a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
2922b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2923b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
29240a708f8fSGustavo F. Padovan {
29250a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
29260a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
29270a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
29280a708f8fSGustavo F. Padovan 	int len, count;
29290a708f8fSGustavo F. Padovan 
2930b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29310a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
29320a708f8fSGustavo F. Padovan 
2933300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2934300b962eSAnderson Lizardo 		return NULL;
2935300b962eSAnderson Lizardo 
29360a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29370a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
29380a708f8fSGustavo F. Padovan 
29398bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
29400a708f8fSGustavo F. Padovan 	if (!skb)
29410a708f8fSGustavo F. Padovan 		return NULL;
29420a708f8fSGustavo F. Padovan 
29434df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
29440a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29453300d9a9SClaudio Takahasi 
29463300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
2947dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29483300d9a9SClaudio Takahasi 	else
2949dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
29500a708f8fSGustavo F. Padovan 
29514df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
29520a708f8fSGustavo F. Padovan 	cmd->code  = code;
29530a708f8fSGustavo F. Padovan 	cmd->ident = ident;
29540a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
29550a708f8fSGustavo F. Padovan 
29560a708f8fSGustavo F. Padovan 	if (dlen) {
29570a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
295859ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
29590a708f8fSGustavo F. Padovan 		data += count;
29600a708f8fSGustavo F. Padovan 	}
29610a708f8fSGustavo F. Padovan 
29620a708f8fSGustavo F. Padovan 	len -= skb->len;
29630a708f8fSGustavo F. Padovan 
29640a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
29650a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
29660a708f8fSGustavo F. Padovan 	while (len) {
29670a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
29680a708f8fSGustavo F. Padovan 
29698bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
29700a708f8fSGustavo F. Padovan 		if (!*frag)
29710a708f8fSGustavo F. Padovan 			goto fail;
29720a708f8fSGustavo F. Padovan 
297359ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
29740a708f8fSGustavo F. Padovan 
29750a708f8fSGustavo F. Padovan 		len  -= count;
29760a708f8fSGustavo F. Padovan 		data += count;
29770a708f8fSGustavo F. Padovan 
29780a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
29790a708f8fSGustavo F. Padovan 	}
29800a708f8fSGustavo F. Padovan 
29810a708f8fSGustavo F. Padovan 	return skb;
29820a708f8fSGustavo F. Padovan 
29830a708f8fSGustavo F. Padovan fail:
29840a708f8fSGustavo F. Padovan 	kfree_skb(skb);
29850a708f8fSGustavo F. Padovan 	return NULL;
29860a708f8fSGustavo F. Padovan }
29870a708f8fSGustavo F. Padovan 
29882d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
29892d792818SGustavo Padovan 				     unsigned long *val)
29900a708f8fSGustavo F. Padovan {
29910a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
29920a708f8fSGustavo F. Padovan 	int len;
29930a708f8fSGustavo F. Padovan 
29940a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
29950a708f8fSGustavo F. Padovan 	*ptr += len;
29960a708f8fSGustavo F. Padovan 
29970a708f8fSGustavo F. Padovan 	*type = opt->type;
29980a708f8fSGustavo F. Padovan 	*olen = opt->len;
29990a708f8fSGustavo F. Padovan 
30000a708f8fSGustavo F. Padovan 	switch (opt->len) {
30010a708f8fSGustavo F. Padovan 	case 1:
30020a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
30030a708f8fSGustavo F. Padovan 		break;
30040a708f8fSGustavo F. Padovan 
30050a708f8fSGustavo F. Padovan 	case 2:
30060a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
30070a708f8fSGustavo F. Padovan 		break;
30080a708f8fSGustavo F. Padovan 
30090a708f8fSGustavo F. Padovan 	case 4:
30100a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
30110a708f8fSGustavo F. Padovan 		break;
30120a708f8fSGustavo F. Padovan 
30130a708f8fSGustavo F. Padovan 	default:
30140a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
30150a708f8fSGustavo F. Padovan 		break;
30160a708f8fSGustavo F. Padovan 	}
30170a708f8fSGustavo F. Padovan 
3018b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30190a708f8fSGustavo F. Padovan 	return len;
30200a708f8fSGustavo F. Padovan }
30210a708f8fSGustavo F. Padovan 
3022e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
30230a708f8fSGustavo F. Padovan {
30240a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
30250a708f8fSGustavo F. Padovan 
3026b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30270a708f8fSGustavo F. Padovan 
3028e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3029e860d2c9SBen Seri 		return;
3030e860d2c9SBen Seri 
30310a708f8fSGustavo F. Padovan 	opt->type = type;
30320a708f8fSGustavo F. Padovan 	opt->len  = len;
30330a708f8fSGustavo F. Padovan 
30340a708f8fSGustavo F. Padovan 	switch (len) {
30350a708f8fSGustavo F. Padovan 	case 1:
30360a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
30370a708f8fSGustavo F. Padovan 		break;
30380a708f8fSGustavo F. Padovan 
30390a708f8fSGustavo F. Padovan 	case 2:
30400a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
30410a708f8fSGustavo F. Padovan 		break;
30420a708f8fSGustavo F. Padovan 
30430a708f8fSGustavo F. Padovan 	case 4:
30440a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
30450a708f8fSGustavo F. Padovan 		break;
30460a708f8fSGustavo F. Padovan 
30470a708f8fSGustavo F. Padovan 	default:
30480a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
30490a708f8fSGustavo F. Padovan 		break;
30500a708f8fSGustavo F. Padovan 	}
30510a708f8fSGustavo F. Padovan 
30520a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
30530a708f8fSGustavo F. Padovan }
30540a708f8fSGustavo F. Padovan 
3055e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3056f89cef09SAndrei Emeltchenko {
3057f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3058f89cef09SAndrei Emeltchenko 
3059f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3060f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3061f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3062f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3063f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3064f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3065dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3066dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3067f89cef09SAndrei Emeltchenko 		break;
3068f89cef09SAndrei Emeltchenko 
3069f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3070f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3071f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3072f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3073f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3074f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3075f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3076f89cef09SAndrei Emeltchenko 		break;
3077f89cef09SAndrei Emeltchenko 
3078f89cef09SAndrei Emeltchenko 	default:
3079f89cef09SAndrei Emeltchenko 		return;
3080f89cef09SAndrei Emeltchenko 	}
3081f89cef09SAndrei Emeltchenko 
3082f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3083e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3084f89cef09SAndrei Emeltchenko }
3085f89cef09SAndrei Emeltchenko 
3086721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
30870a708f8fSGustavo F. Padovan {
3088721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3089721c4181SGustavo F. Padovan 					       ack_timer.work);
30900362520bSMat Martineau 	u16 frames_to_ack;
30910a708f8fSGustavo F. Padovan 
30922fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
30932fb9b3d4SGustavo F. Padovan 
30946be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
30956be36555SAndrei Emeltchenko 
30960362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
30970362520bSMat Martineau 				     chan->last_acked_seq);
30980362520bSMat Martineau 
30990362520bSMat Martineau 	if (frames_to_ack)
31000362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
31016be36555SAndrei Emeltchenko 
31026be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
310309bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
31040a708f8fSGustavo F. Padovan }
31050a708f8fSGustavo F. Padovan 
3106466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
31070a708f8fSGustavo F. Padovan {
31083c588192SMat Martineau 	int err;
31093c588192SMat Martineau 
3110105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3111105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
311242e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
31136a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
311442e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
31156a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3116105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3117105bdf9eSMat Martineau 	chan->sdu = NULL;
3118105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3119105bdf9eSMat Martineau 	chan->sdu_len = 0;
3120105bdf9eSMat Martineau 
3121d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3122d34c34fbSMat Martineau 
31236ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
31246ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
312508333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
312608333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
312708333283SMat Martineau 
3128105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3129105bdf9eSMat Martineau 		return 0;
3130105bdf9eSMat Martineau 
3131105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3132105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
31330a708f8fSGustavo F. Padovan 
3134721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3135721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3136721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
31370a708f8fSGustavo F. Padovan 
3138f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
31390a708f8fSGustavo F. Padovan 
31403c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31413c588192SMat Martineau 	if (err < 0)
31423c588192SMat Martineau 		return err;
31433c588192SMat Martineau 
31449dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31459dc9affcSMat Martineau 	if (err < 0)
31469dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
31479dc9affcSMat Martineau 
31489dc9affcSMat Martineau 	return err;
31490a708f8fSGustavo F. Padovan }
31500a708f8fSGustavo F. Padovan 
31510a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31520a708f8fSGustavo F. Padovan {
31530a708f8fSGustavo F. Padovan 	switch (mode) {
31540a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
31550a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
31560a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
31570a708f8fSGustavo F. Padovan 			return mode;
31580a708f8fSGustavo F. Padovan 		/* fall through */
31590a708f8fSGustavo F. Padovan 	default:
31600a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
31610a708f8fSGustavo F. Padovan 	}
31620a708f8fSGustavo F. Padovan }
31630a708f8fSGustavo F. Padovan 
3164848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31656327eb98SAndrei Emeltchenko {
31660bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
31670bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
31686327eb98SAndrei Emeltchenko }
31696327eb98SAndrei Emeltchenko 
3170848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3171f89cef09SAndrei Emeltchenko {
31720bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
31730bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3174f89cef09SAndrei Emeltchenko }
3175f89cef09SAndrei Emeltchenko 
317636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
317736c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
317836c86c85SMat Martineau {
31796ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
318036c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
318136c86c85SMat Martineau 
318236c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
318336c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
318436c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
318536c86c85SMat Martineau 		 * controllers is 10 seconds.
318636c86c85SMat Martineau 		 *
318736c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
318836c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
318936c86c85SMat Martineau 		 * will result in a timeout that meets the above
319036c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
319136c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
319236c86c85SMat Martineau 		 */
319336c86c85SMat Martineau 
319436c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
319536c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
319636c86c85SMat Martineau 
319736c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
319836c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
319936c86c85SMat Martineau 		 * controller.
320036c86c85SMat Martineau 		 */
320136c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
320236c86c85SMat Martineau 
320336c86c85SMat Martineau 		if (ertm_to > 0xffff)
320436c86c85SMat Martineau 			ertm_to = 0xffff;
320536c86c85SMat Martineau 
320636c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
320736c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
320836c86c85SMat Martineau 	} else {
3209dcf4adbfSJoe Perches 		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3210dcf4adbfSJoe Perches 		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
321136c86c85SMat Martineau 	}
321236c86c85SMat Martineau }
321336c86c85SMat Martineau 
32146327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
32156327eb98SAndrei Emeltchenko {
32166327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3217848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
32186327eb98SAndrei Emeltchenko 		/* use extended control field */
32196327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3220836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3221836be934SAndrei Emeltchenko 	} else {
32226327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
32236327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3224836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3225836be934SAndrei Emeltchenko 	}
3226c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
32276327eb98SAndrei Emeltchenko }
32286327eb98SAndrei Emeltchenko 
3229e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
32300a708f8fSGustavo F. Padovan {
32310a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
32320c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32330a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3234e860d2c9SBen Seri 	void *endptr = data + data_size;
3235c8f79162SAndrei Emeltchenko 	u16 size;
32360a708f8fSGustavo F. Padovan 
323749208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
32380a708f8fSGustavo F. Padovan 
323973ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
32400a708f8fSGustavo F. Padovan 		goto done;
32410a708f8fSGustavo F. Padovan 
32420c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32430a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
32440a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3245c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32460a708f8fSGustavo F. Padovan 			break;
32470a708f8fSGustavo F. Padovan 
3248848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3249f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3250f89cef09SAndrei Emeltchenko 
32510a708f8fSGustavo F. Padovan 		/* fall through */
32520a708f8fSGustavo F. Padovan 	default:
32538c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32540a708f8fSGustavo F. Padovan 		break;
32550a708f8fSGustavo F. Padovan 	}
32560a708f8fSGustavo F. Padovan 
32570a708f8fSGustavo F. Padovan done:
32580c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
3259e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
32600a708f8fSGustavo F. Padovan 
32610c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
32636fea7ad1SMarcel Holtmann 		if (disable_ertm)
32646fea7ad1SMarcel Holtmann 			break;
32656fea7ad1SMarcel Holtmann 
32668c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32678c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32680a708f8fSGustavo F. Padovan 			break;
32690a708f8fSGustavo F. Padovan 
32700a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
32710a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
32720a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
32730a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
32740a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
32750a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
32760a708f8fSGustavo F. Padovan 
32770a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3278e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
32790a708f8fSGustavo F. Padovan 		break;
32800a708f8fSGustavo F. Padovan 
32810a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
32820a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
328347d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
328436c86c85SMat Martineau 
328536c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3286c8f79162SAndrei Emeltchenko 
3287c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
32882d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3289c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3290c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
32910a708f8fSGustavo F. Padovan 
32926327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
32936327eb98SAndrei Emeltchenko 
32946327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
32956327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
32960a708f8fSGustavo F. Padovan 
32970a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3298e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
32990a708f8fSGustavo F. Padovan 
3300f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3301e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3302f89cef09SAndrei Emeltchenko 
33036327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
33046327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3305e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
330660918918SAndrei Emeltchenko 
330760918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
330860918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3309f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
331060918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
331160918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3312e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
331360918918SAndrei Emeltchenko 			}
33140a708f8fSGustavo F. Padovan 		break;
33150a708f8fSGustavo F. Padovan 
33160a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3317273759e2SMat Martineau 		l2cap_txwin_setup(chan);
33180a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
33190a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
33200a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
33210a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
33220a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3323c8f79162SAndrei Emeltchenko 
3324c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33252d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3326c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3327c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
33280a708f8fSGustavo F. Padovan 
33290a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3330e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
33310a708f8fSGustavo F. Padovan 
3332f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3333e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3334f89cef09SAndrei Emeltchenko 
333560918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
333647d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3337f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
333847d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
333960918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3340e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
33410a708f8fSGustavo F. Padovan 			}
33420a708f8fSGustavo F. Padovan 		break;
33430a708f8fSGustavo F. Padovan 	}
33440a708f8fSGustavo F. Padovan 
3345fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3346dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
33470a708f8fSGustavo F. Padovan 
33480a708f8fSGustavo F. Padovan 	return ptr - data;
33490a708f8fSGustavo F. Padovan }
33500a708f8fSGustavo F. Padovan 
3351e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33520a708f8fSGustavo F. Padovan {
33530a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
33540a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3355e860d2c9SBen Seri 	void *endptr = data + data_size;
335673ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
335773ffa904SGustavo F. Padovan 	int len = chan->conf_len;
33580a708f8fSGustavo F. Padovan 	int type, hint, olen;
33590a708f8fSGustavo F. Padovan 	unsigned long val;
33600a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
336142dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
336242dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
33630a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
33640a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3365c8f79162SAndrei Emeltchenko 	u16 size;
33660a708f8fSGustavo F. Padovan 
336773ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
33680a708f8fSGustavo F. Padovan 
33690a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33700a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33717c9cbd0bSMarcel Holtmann 		if (len < 0)
33727c9cbd0bSMarcel Holtmann 			break;
33730a708f8fSGustavo F. Padovan 
33740a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
33750a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
33760a708f8fSGustavo F. Padovan 
33770a708f8fSGustavo F. Padovan 		switch (type) {
33780a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3379af3d5d1cSMarcel Holtmann 			if (olen != 2)
3380af3d5d1cSMarcel Holtmann 				break;
33810a708f8fSGustavo F. Padovan 			mtu = val;
33820a708f8fSGustavo F. Padovan 			break;
33830a708f8fSGustavo F. Padovan 
33840a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3385af3d5d1cSMarcel Holtmann 			if (olen != 2)
3386af3d5d1cSMarcel Holtmann 				break;
33870c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
33880a708f8fSGustavo F. Padovan 			break;
33890a708f8fSGustavo F. Padovan 
33900a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
33910a708f8fSGustavo F. Padovan 			break;
33920a708f8fSGustavo F. Padovan 
33930a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3394af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3395af3d5d1cSMarcel Holtmann 				break;
33960a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
33970a708f8fSGustavo F. Padovan 			break;
33980a708f8fSGustavo F. Padovan 
33990a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3400af3d5d1cSMarcel Holtmann 			if (olen != 1)
3401af3d5d1cSMarcel Holtmann 				break;
34020a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3403f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
340442dceae2SAndrei Emeltchenko 			break;
34050a708f8fSGustavo F. Padovan 
340642dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3407af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3408af3d5d1cSMarcel Holtmann 				break;
340942dceae2SAndrei Emeltchenko 			remote_efs = 1;
341042dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
34110a708f8fSGustavo F. Padovan 			break;
34120a708f8fSGustavo F. Padovan 
34136327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3414af3d5d1cSMarcel Holtmann 			if (olen != 2)
3415af3d5d1cSMarcel Holtmann 				break;
34160bd49fc7SJohan Hedberg 			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
34176327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
34186327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
34196327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3420836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
34216327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
34220a708f8fSGustavo F. Padovan 			break;
34230a708f8fSGustavo F. Padovan 
34240a708f8fSGustavo F. Padovan 		default:
34250a708f8fSGustavo F. Padovan 			if (hint)
34260a708f8fSGustavo F. Padovan 				break;
34270a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
34280a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
34290a708f8fSGustavo F. Padovan 			break;
34300a708f8fSGustavo F. Padovan 		}
34310a708f8fSGustavo F. Padovan 	}
34320a708f8fSGustavo F. Padovan 
343373ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
34340a708f8fSGustavo F. Padovan 		goto done;
34350a708f8fSGustavo F. Padovan 
34360c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34370a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34380a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3439c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
34400c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
34418c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
34420a708f8fSGustavo F. Padovan 			break;
34430a708f8fSGustavo F. Padovan 		}
34440a708f8fSGustavo F. Padovan 
344542dceae2SAndrei Emeltchenko 		if (remote_efs) {
3446848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
344742dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
344842dceae2SAndrei Emeltchenko 			else
344942dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
345042dceae2SAndrei Emeltchenko 		}
345142dceae2SAndrei Emeltchenko 
34520c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
34530a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34540a708f8fSGustavo F. Padovan 
34550a708f8fSGustavo F. Padovan 		break;
34560a708f8fSGustavo F. Padovan 	}
34570a708f8fSGustavo F. Padovan 
34580a708f8fSGustavo F. Padovan done:
34590c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
34600a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
34610c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
34620a708f8fSGustavo F. Padovan 
346373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
34640a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34650a708f8fSGustavo F. Padovan 
34662d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3467e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34680a708f8fSGustavo F. Padovan 	}
34690a708f8fSGustavo F. Padovan 
34700a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
34710a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
34720a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
34730a708f8fSGustavo F. Padovan 
34740a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
34750a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
34760a708f8fSGustavo F. Padovan 		else {
34770c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3478c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
34790a708f8fSGustavo F. Padovan 		}
3480e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34810a708f8fSGustavo F. Padovan 
348242dceae2SAndrei Emeltchenko 		if (remote_efs) {
348342dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
348442dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
348542dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
348642dceae2SAndrei Emeltchenko 
348742dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
348842dceae2SAndrei Emeltchenko 
348942dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
349042dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
349142dceae2SAndrei Emeltchenko 
349242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
349342dceae2SAndrei Emeltchenko 						   sizeof(efs),
3494e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
34950e8b207eSAndrei Emeltchenko 			} else {
34963e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
34970e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
34980e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
349942dceae2SAndrei Emeltchenko 			}
350042dceae2SAndrei Emeltchenko 		}
350142dceae2SAndrei Emeltchenko 
35020a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
35030a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
350447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3505c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35060a708f8fSGustavo F. Padovan 			break;
35070a708f8fSGustavo F. Padovan 
35080a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
35096327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
35102c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
35116327eb98SAndrei Emeltchenko 			else
35126327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
35136327eb98SAndrei Emeltchenko 
35142c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
35150a708f8fSGustavo F. Padovan 
3516c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35172d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35182d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3519c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3520c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35210a708f8fSGustavo F. Padovan 
352236c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
35230a708f8fSGustavo F. Padovan 
3524c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35250a708f8fSGustavo F. Padovan 
35260a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3527e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35280a708f8fSGustavo F. Padovan 
352942dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
353042dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
353142dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
353242dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
353342dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
353442dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
353542dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
353642dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
353742dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
353842dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
353942dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35402d792818SGustavo Padovan 						   sizeof(efs),
3541e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
354242dceae2SAndrei Emeltchenko 			}
35430a708f8fSGustavo F. Padovan 			break;
35440a708f8fSGustavo F. Padovan 
35450a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3546c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35472d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35482d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3549c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3550c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35510a708f8fSGustavo F. Padovan 
3552c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35530a708f8fSGustavo F. Padovan 
35542d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3555e860d2c9SBen Seri 					   (unsigned long) &rfc, endptr - ptr);
35560a708f8fSGustavo F. Padovan 
35570a708f8fSGustavo F. Padovan 			break;
35580a708f8fSGustavo F. Padovan 
35590a708f8fSGustavo F. Padovan 		default:
35600a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
35610a708f8fSGustavo F. Padovan 
35620a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
35630c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
35640a708f8fSGustavo F. Padovan 		}
35650a708f8fSGustavo F. Padovan 
35660a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3567c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35680a708f8fSGustavo F. Padovan 	}
3569fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
35700a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
3571dcf4adbfSJoe Perches 	rsp->flags  = cpu_to_le16(0);
35720a708f8fSGustavo F. Padovan 
35730a708f8fSGustavo F. Padovan 	return ptr - data;
35740a708f8fSGustavo F. Padovan }
35750a708f8fSGustavo F. Padovan 
35762d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3577e860d2c9SBen Seri 				void *data, size_t size, u16 *result)
35780a708f8fSGustavo F. Padovan {
35790a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
35800a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3581e860d2c9SBen Seri 	void *endptr = data + size;
35820a708f8fSGustavo F. Padovan 	int type, olen;
35830a708f8fSGustavo F. Padovan 	unsigned long val;
358436e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
358566af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
35860a708f8fSGustavo F. Padovan 
3587fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
35880a708f8fSGustavo F. Padovan 
35890a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35900a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
35917c9cbd0bSMarcel Holtmann 		if (len < 0)
35927c9cbd0bSMarcel Holtmann 			break;
35930a708f8fSGustavo F. Padovan 
35940a708f8fSGustavo F. Padovan 		switch (type) {
35950a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3596af3d5d1cSMarcel Holtmann 			if (olen != 2)
3597af3d5d1cSMarcel Holtmann 				break;
35980a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
35990a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
36000c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
36010a708f8fSGustavo F. Padovan 			} else
36020c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
3603af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3604af3d5d1cSMarcel Holtmann 					   endptr - ptr);
36050a708f8fSGustavo F. Padovan 			break;
36060a708f8fSGustavo F. Padovan 
36070a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3608af3d5d1cSMarcel Holtmann 			if (olen != 2)
3609af3d5d1cSMarcel Holtmann 				break;
36100c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
3611af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3612af3d5d1cSMarcel Holtmann 					   chan->flush_to, endptr - ptr);
36130a708f8fSGustavo F. Padovan 			break;
36140a708f8fSGustavo F. Padovan 
36150a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3616af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3617af3d5d1cSMarcel Holtmann 				break;
36180a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3619c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
36200c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
36210a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
362247d1ec61SGustavo F. Padovan 			chan->fcs = 0;
3623af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3624af3d5d1cSMarcel Holtmann 					   (unsigned long) &rfc, endptr - ptr);
36250a708f8fSGustavo F. Padovan 			break;
36266327eb98SAndrei Emeltchenko 
36276327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3628af3d5d1cSMarcel Holtmann 			if (olen != 2)
3629af3d5d1cSMarcel Holtmann 				break;
3630c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
36313e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3632e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
36336327eb98SAndrei Emeltchenko 			break;
363466af7aafSAndrei Emeltchenko 
363566af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3636af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3637af3d5d1cSMarcel Holtmann 				break;
363866af7aafSAndrei Emeltchenko 			memcpy(&efs, (void *)val, olen);
363966af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
364066af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
364166af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
364266af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
36432d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3644e860d2c9SBen Seri 					   (unsigned long) &efs, endptr - ptr);
364566af7aafSAndrei Emeltchenko 			break;
3646cbabee78SAndrei Emeltchenko 
3647cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3648af3d5d1cSMarcel Holtmann 			if (olen != 1)
3649af3d5d1cSMarcel Holtmann 				break;
3650cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3651cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3652f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3653cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3654cbabee78SAndrei Emeltchenko 			break;
36550a708f8fSGustavo F. Padovan 		}
36560a708f8fSGustavo F. Padovan 	}
36570a708f8fSGustavo F. Padovan 
36580c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36590a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
36600a708f8fSGustavo F. Padovan 
36610c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
36620a708f8fSGustavo F. Padovan 
36630e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36640a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36650a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
366647d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
366747d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
366847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3669c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3670c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3671c20f8e35SMat Martineau 						      rfc.txwin_size);
367266af7aafSAndrei Emeltchenko 
367366af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
367466af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
367566af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
367666af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
367766af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
367866af7aafSAndrei Emeltchenko 				chan->local_flush_to =
367966af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
368066af7aafSAndrei Emeltchenko 			}
36810a708f8fSGustavo F. Padovan 			break;
368266af7aafSAndrei Emeltchenko 
36830a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
368447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
36850a708f8fSGustavo F. Padovan 		}
36860a708f8fSGustavo F. Padovan 	}
36870a708f8fSGustavo F. Padovan 
3688fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
3689dcf4adbfSJoe Perches 	req->flags  = cpu_to_le16(0);
36900a708f8fSGustavo F. Padovan 
36910a708f8fSGustavo F. Padovan 	return ptr - data;
36920a708f8fSGustavo F. Padovan }
36930a708f8fSGustavo F. Padovan 
36942d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
36952d792818SGustavo Padovan 				u16 result, u16 flags)
36960a708f8fSGustavo F. Padovan {
36970a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
36980a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
36990a708f8fSGustavo F. Padovan 
3700fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
37010a708f8fSGustavo F. Padovan 
3702fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37030a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
37040a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
37050a708f8fSGustavo F. Padovan 
37060a708f8fSGustavo F. Padovan 	return ptr - data;
37070a708f8fSGustavo F. Padovan }
37080a708f8fSGustavo F. Padovan 
370927e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
371027e2d4c8SJohan Hedberg {
371127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
371227e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
371327e2d4c8SJohan Hedberg 
371427e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
371527e2d4c8SJohan Hedberg 
371627e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
371727e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
37183916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
37190cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
3720571f7390SMallikarjun Phulari 	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
372127e2d4c8SJohan Hedberg 
372227e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
372327e2d4c8SJohan Hedberg 		       &rsp);
372427e2d4c8SJohan Hedberg }
372527e2d4c8SJohan Hedberg 
37268c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3727710f9b0aSGustavo F. Padovan {
3728710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
37298c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3730710f9b0aSGustavo F. Padovan 	u8 buf[128];
3731439f34acSAndrei Emeltchenko 	u8 rsp_code;
3732710f9b0aSGustavo F. Padovan 
3733fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3734fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3735dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3736dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3737439f34acSAndrei Emeltchenko 
3738439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3739439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3740439f34acSAndrei Emeltchenko 	else
3741439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3742439f34acSAndrei Emeltchenko 
3743439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3744439f34acSAndrei Emeltchenko 
3745439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3746710f9b0aSGustavo F. Padovan 
3747c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3748710f9b0aSGustavo F. Padovan 		return;
3749710f9b0aSGustavo F. Padovan 
3750710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3751e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
3752710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3753710f9b0aSGustavo F. Padovan }
3754710f9b0aSGustavo F. Padovan 
375547d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
37560a708f8fSGustavo F. Padovan {
37570a708f8fSGustavo F. Padovan 	int type, olen;
37580a708f8fSGustavo F. Padovan 	unsigned long val;
3759c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3760c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3761c20f8e35SMat Martineau 	 */
3762c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3763c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3764c20f8e35SMat Martineau 		.mode = chan->mode,
3765dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3766dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3767c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3768c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3769c20f8e35SMat Martineau 	};
37700a708f8fSGustavo F. Padovan 
377147d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
37720a708f8fSGustavo F. Padovan 
37730c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
37740a708f8fSGustavo F. Padovan 		return;
37750a708f8fSGustavo F. Padovan 
37760a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37770a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37787c9cbd0bSMarcel Holtmann 		if (len < 0)
37797c9cbd0bSMarcel Holtmann 			break;
37800a708f8fSGustavo F. Padovan 
3781c20f8e35SMat Martineau 		switch (type) {
3782c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3783af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3784af3d5d1cSMarcel Holtmann 				break;
37850a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3786c20f8e35SMat Martineau 			break;
3787c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3788af3d5d1cSMarcel Holtmann 			if (olen != 2)
3789af3d5d1cSMarcel Holtmann 				break;
3790c20f8e35SMat Martineau 			txwin_ext = val;
3791c20f8e35SMat Martineau 			break;
3792c20f8e35SMat Martineau 		}
37930a708f8fSGustavo F. Padovan 	}
37940a708f8fSGustavo F. Padovan 
37950a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
37960a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
379747d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
379847d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
379947d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3800c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3801c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3802c20f8e35SMat Martineau 		else
3803c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3804c20f8e35SMat Martineau 					      rfc.txwin_size);
38050a708f8fSGustavo F. Padovan 		break;
38060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
380747d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38080a708f8fSGustavo F. Padovan 	}
38090a708f8fSGustavo F. Padovan }
38100a708f8fSGustavo F. Padovan 
38112d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3812cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3813cb3b3152SJohan Hedberg 				    u8 *data)
38140a708f8fSGustavo F. Padovan {
3815e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
38160a708f8fSGustavo F. Padovan 
3817cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3818cb3b3152SJohan Hedberg 		return -EPROTO;
3819cb3b3152SJohan Hedberg 
3820e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
38210a708f8fSGustavo F. Padovan 		return 0;
38220a708f8fSGustavo F. Padovan 
38230a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
38240a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
382517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
38260a708f8fSGustavo F. Padovan 
38270a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
38280a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
38290a708f8fSGustavo F. Padovan 
38300a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
38310a708f8fSGustavo F. Padovan 	}
38320a708f8fSGustavo F. Padovan 
38330a708f8fSGustavo F. Padovan 	return 0;
38340a708f8fSGustavo F. Padovan }
38350a708f8fSGustavo F. Padovan 
38361700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
38371700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
38384c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
38390a708f8fSGustavo F. Padovan {
38400a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
38410a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
384223691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
38430a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
38440a708f8fSGustavo F. Padovan 
38450a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
38460a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
38470a708f8fSGustavo F. Padovan 
3848097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
38490a708f8fSGustavo F. Padovan 
38500a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
38516f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3852bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
385323691d75SGustavo F. Padovan 	if (!pchan) {
38540a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
38550a708f8fSGustavo F. Padovan 		goto sendresp;
38560a708f8fSGustavo F. Padovan 	}
38570a708f8fSGustavo F. Padovan 
38583df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38598ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
38600a708f8fSGustavo F. Padovan 
38610a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
3862dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
38630a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
38649f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
38650a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
38660a708f8fSGustavo F. Padovan 		goto response;
38670a708f8fSGustavo F. Padovan 	}
38680a708f8fSGustavo F. Padovan 
38690a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
38700a708f8fSGustavo F. Padovan 
3871dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
3872dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
3873dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
38742dfa1003SGustavo Padovan 		goto response;
3875dd1a8f8aSMallikarjun Phulari 	}
3876dd1a8f8aSMallikarjun Phulari 
3877dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
3878dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
3879dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
3880dd1a8f8aSMallikarjun Phulari 		goto response;
3881dd1a8f8aSMallikarjun Phulari 	}
38822dfa1003SGustavo Padovan 
388380b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
388480808e43SGustavo F. Padovan 	if (!chan)
38850a708f8fSGustavo F. Padovan 		goto response;
38860a708f8fSGustavo F. Padovan 
3887330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
3888330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
3889330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
3890330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3891330b6c15SSyam Sidhardhan 	 */
3892330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3893330b6c15SSyam Sidhardhan 
38947eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
38957eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
3896a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
3897a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
3898fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3899fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
39001700915fSMat Martineau 	chan->local_amp_id = amp_id;
39010a708f8fSGustavo F. Padovan 
39026be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
390348454079SGustavo F. Padovan 
3904fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
39050a708f8fSGustavo F. Padovan 
39068d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
39070a708f8fSGustavo F. Padovan 
3908fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
39090a708f8fSGustavo F. Padovan 
39100a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3911e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
3912bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
3913f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
39140a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
39150a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
39162dc4e510SGustavo Padovan 				chan->ops->defer(chan);
39170a708f8fSGustavo F. Padovan 			} else {
39181700915fSMat Martineau 				/* Force pending result for AMP controllers.
39191700915fSMat Martineau 				 * The connection will succeed after the
39201700915fSMat Martineau 				 * physical link is up.
39211700915fSMat Martineau 				 */
39226ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
3923f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
39240a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
39256ed971caSMarcel Holtmann 				} else {
3926f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
39276ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
39281700915fSMat Martineau 				}
39290a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
39300a708f8fSGustavo F. Padovan 			}
39310a708f8fSGustavo F. Padovan 		} else {
3932f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
39330a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
39340a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
39350a708f8fSGustavo F. Padovan 		}
39360a708f8fSGustavo F. Padovan 	} else {
3937f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
39380a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
39390a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
39400a708f8fSGustavo F. Padovan 	}
39410a708f8fSGustavo F. Padovan 
39420a708f8fSGustavo F. Padovan response:
39438ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
39443df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3945a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
39460a708f8fSGustavo F. Padovan 
39470a708f8fSGustavo F. Padovan sendresp:
39480a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
39490a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
39500a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
39510a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
39524c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
39530a708f8fSGustavo F. Padovan 
39540a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
39550a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
3956dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
39570a708f8fSGustavo F. Padovan 
39580a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
39590a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
39600a708f8fSGustavo F. Padovan 
3961ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
39620a708f8fSGustavo F. Padovan 
39632d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
39642d792818SGustavo Padovan 			       sizeof(info), &info);
39650a708f8fSGustavo F. Padovan 	}
39660a708f8fSGustavo F. Padovan 
3967c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
39680a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
39690a708f8fSGustavo F. Padovan 		u8 buf[128];
3970c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
39710a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3972e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
397373ffa904SGustavo F. Padovan 		chan->num_conf_req++;
39740a708f8fSGustavo F. Padovan 	}
39751700915fSMat Martineau 
39761700915fSMat Martineau 	return chan;
39774c89b6aaSMat Martineau }
39780a708f8fSGustavo F. Padovan 
39794c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
3980cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
39814c89b6aaSMat Martineau {
39827b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
39837b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
39847b064edaSJaganath Kanakkassery 
3985cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
3986cb3b3152SJohan Hedberg 		return -EPROTO;
3987cb3b3152SJohan Hedberg 
39887b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
3989d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
39907b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
399148ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, hcon, 0, NULL, 0);
39927b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
39937b064edaSJaganath Kanakkassery 
3994300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
39950a708f8fSGustavo F. Padovan 	return 0;
39960a708f8fSGustavo F. Padovan }
39970a708f8fSGustavo F. Padovan 
39985909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
3999cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4000cb3b3152SJohan Hedberg 				    u8 *data)
40010a708f8fSGustavo F. Padovan {
40020a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
40030a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
400448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
40050a708f8fSGustavo F. Padovan 	u8 req[128];
40063df91ea2SAndrei Emeltchenko 	int err;
40070a708f8fSGustavo F. Padovan 
4008cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4009cb3b3152SJohan Hedberg 		return -EPROTO;
4010cb3b3152SJohan Hedberg 
40110a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
40120a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
40130a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
40140a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
40150a708f8fSGustavo F. Padovan 
40161b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
40171b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
40180a708f8fSGustavo F. Padovan 
40193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
40203df91ea2SAndrei Emeltchenko 
40210a708f8fSGustavo F. Padovan 	if (scid) {
40223df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
40233df91ea2SAndrei Emeltchenko 		if (!chan) {
402421870b52SJohan Hedberg 			err = -EBADSLT;
40253df91ea2SAndrei Emeltchenko 			goto unlock;
40263df91ea2SAndrei Emeltchenko 		}
40270a708f8fSGustavo F. Padovan 	} else {
40283df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
40293df91ea2SAndrei Emeltchenko 		if (!chan) {
403021870b52SJohan Hedberg 			err = -EBADSLT;
40313df91ea2SAndrei Emeltchenko 			goto unlock;
40323df91ea2SAndrei Emeltchenko 		}
40330a708f8fSGustavo F. Padovan 	}
40340a708f8fSGustavo F. Padovan 
40353df91ea2SAndrei Emeltchenko 	err = 0;
40363df91ea2SAndrei Emeltchenko 
40376be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
403848454079SGustavo F. Padovan 
40390a708f8fSGustavo F. Padovan 	switch (result) {
40400a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
404189bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4042fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4043fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4044c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
40450a708f8fSGustavo F. Padovan 
4046c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
40470a708f8fSGustavo F. Padovan 			break;
40480a708f8fSGustavo F. Padovan 
40490a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4050e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
405173ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40520a708f8fSGustavo F. Padovan 		break;
40530a708f8fSGustavo F. Padovan 
40540a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4055c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
40560a708f8fSGustavo F. Padovan 		break;
40570a708f8fSGustavo F. Padovan 
40580a708f8fSGustavo F. Padovan 	default:
405948454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
40600a708f8fSGustavo F. Padovan 		break;
40610a708f8fSGustavo F. Padovan 	}
40620a708f8fSGustavo F. Padovan 
40636be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
40643df91ea2SAndrei Emeltchenko 
40653df91ea2SAndrei Emeltchenko unlock:
40663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40673df91ea2SAndrei Emeltchenko 
40683df91ea2SAndrei Emeltchenko 	return err;
40690a708f8fSGustavo F. Padovan }
40700a708f8fSGustavo F. Padovan 
407147d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
40720a708f8fSGustavo F. Padovan {
40730a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
40740a708f8fSGustavo F. Padovan 	 * sides request it.
40750a708f8fSGustavo F. Padovan 	 */
40760c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
407747d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4078f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
407947d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
40800a708f8fSGustavo F. Padovan }
40810a708f8fSGustavo F. Padovan 
408229d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
408329d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
408429d8a590SAndrei Emeltchenko {
408529d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
408629d8a590SAndrei Emeltchenko 
408729d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
408829d8a590SAndrei Emeltchenko 	       flags);
408929d8a590SAndrei Emeltchenko 
409029d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
409129d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
409229d8a590SAndrei Emeltchenko 
409329d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
409429d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
409529d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
409629d8a590SAndrei Emeltchenko }
409729d8a590SAndrei Emeltchenko 
4098662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4099662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4100662d652dSJohan Hedberg {
4101662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4102662d652dSJohan Hedberg 
4103dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4104662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4105662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4106662d652dSJohan Hedberg 
4107662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4108662d652dSJohan Hedberg }
4109662d652dSJohan Hedberg 
41102d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
41112d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
41122d792818SGustavo Padovan 				   u8 *data)
41130a708f8fSGustavo F. Padovan {
41140a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
41150a708f8fSGustavo F. Padovan 	u16 dcid, flags;
41160a708f8fSGustavo F. Padovan 	u8 rsp[64];
411748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
41183c588192SMat Martineau 	int len, err = 0;
41190a708f8fSGustavo F. Padovan 
4120cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4121cb3b3152SJohan Hedberg 		return -EPROTO;
4122cb3b3152SJohan Hedberg 
41230a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
41240a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
41250a708f8fSGustavo F. Padovan 
41260a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
41270a708f8fSGustavo F. Padovan 
4128baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4129662d652dSJohan Hedberg 	if (!chan) {
4130662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4131662d652dSJohan Hedberg 		return 0;
4132662d652dSJohan Hedberg 	}
41330a708f8fSGustavo F. Padovan 
4134033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4135662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4136662d652dSJohan Hedberg 				       chan->dcid);
41370a708f8fSGustavo F. Padovan 		goto unlock;
41380a708f8fSGustavo F. Padovan 	}
41390a708f8fSGustavo F. Padovan 
41400a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
41410a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4142cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
41430a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4144fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41450a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
41460a708f8fSGustavo F. Padovan 		goto unlock;
41470a708f8fSGustavo F. Padovan 	}
41480a708f8fSGustavo F. Padovan 
41490a708f8fSGustavo F. Padovan 	/* Store config. */
415073ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
415173ffa904SGustavo F. Padovan 	chan->conf_len += len;
41520a708f8fSGustavo F. Padovan 
415359e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
41540a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
41550a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4156fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41575325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
41580a708f8fSGustavo F. Padovan 		goto unlock;
41590a708f8fSGustavo F. Padovan 	}
41600a708f8fSGustavo F. Padovan 
41610a708f8fSGustavo F. Padovan 	/* Complete config. */
4162e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
41630a708f8fSGustavo F. Padovan 	if (len < 0) {
41645e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
41650a708f8fSGustavo F. Padovan 		goto unlock;
41660a708f8fSGustavo F. Padovan 	}
41670a708f8fSGustavo F. Padovan 
41681500109bSMat Martineau 	chan->ident = cmd->ident;
41690a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
417073ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
41710a708f8fSGustavo F. Padovan 
41720a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
417373ffa904SGustavo F. Padovan 	chan->conf_len = 0;
41740a708f8fSGustavo F. Padovan 
4175c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
41760a708f8fSGustavo F. Padovan 		goto unlock;
41770a708f8fSGustavo F. Padovan 
4178c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
417947d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
41800a708f8fSGustavo F. Padovan 
4181105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4182105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
41833c588192SMat Martineau 			err = l2cap_ertm_init(chan);
41840a708f8fSGustavo F. Padovan 
41853c588192SMat Martineau 		if (err < 0)
41865e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
41873c588192SMat Martineau 		else
4188cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
41893c588192SMat Martineau 
41900a708f8fSGustavo F. Padovan 		goto unlock;
41910a708f8fSGustavo F. Padovan 	}
41920a708f8fSGustavo F. Padovan 
4193c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
41940a708f8fSGustavo F. Padovan 		u8 buf[64];
41950a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4196e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
419773ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41980a708f8fSGustavo F. Padovan 	}
41990a708f8fSGustavo F. Padovan 
420049c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
42010e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
42020e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
42030e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42040e8b207eSAndrei Emeltchenko 
42050e8b207eSAndrei Emeltchenko 		/* check compatibility */
42060e8b207eSAndrei Emeltchenko 
420779de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4208f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
420929d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
421079de886dSAndrei Emeltchenko 		else
421179de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
42120e8b207eSAndrei Emeltchenko 	}
42130e8b207eSAndrei Emeltchenko 
42140a708f8fSGustavo F. Padovan unlock:
42156be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
42163c588192SMat Martineau 	return err;
42170a708f8fSGustavo F. Padovan }
42180a708f8fSGustavo F. Padovan 
42192d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4220cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4221cb3b3152SJohan Hedberg 				   u8 *data)
42220a708f8fSGustavo F. Padovan {
42230a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
42240a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
422548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4226cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
42273c588192SMat Martineau 	int err = 0;
42280a708f8fSGustavo F. Padovan 
4229cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4230cb3b3152SJohan Hedberg 		return -EPROTO;
4231cb3b3152SJohan Hedberg 
42320a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
42330a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
42340a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
42350a708f8fSGustavo F. Padovan 
423661386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
423761386cbaSAndrei Emeltchenko 	       result, len);
42380a708f8fSGustavo F. Padovan 
4239baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
424048454079SGustavo F. Padovan 	if (!chan)
42410a708f8fSGustavo F. Padovan 		return 0;
42420a708f8fSGustavo F. Padovan 
42430a708f8fSGustavo F. Padovan 	switch (result) {
42440a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
424547d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
42460e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42470a708f8fSGustavo F. Padovan 		break;
42480a708f8fSGustavo F. Padovan 
42490e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
42500e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42510e8b207eSAndrei Emeltchenko 
42520e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42530e8b207eSAndrei Emeltchenko 			char buf[64];
42540e8b207eSAndrei Emeltchenko 
42550e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4256e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
42570e8b207eSAndrei Emeltchenko 			if (len < 0) {
42585e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42590e8b207eSAndrei Emeltchenko 				goto done;
42600e8b207eSAndrei Emeltchenko 			}
42610e8b207eSAndrei Emeltchenko 
4262f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
426379de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
426479de886dSAndrei Emeltchenko 							0);
42655ce66b59SAndrei Emeltchenko 			} else {
42665ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
42675ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
426879de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
42690e8b207eSAndrei Emeltchenko 				}
42705ce66b59SAndrei Emeltchenko 			}
42715ce66b59SAndrei Emeltchenko 		}
42720e8b207eSAndrei Emeltchenko 		goto done;
42730e8b207eSAndrei Emeltchenko 
42740a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
427573ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
42760a708f8fSGustavo F. Padovan 			char req[64];
42770a708f8fSGustavo F. Padovan 
42780a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
42795e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42800a708f8fSGustavo F. Padovan 				goto done;
42810a708f8fSGustavo F. Padovan 			}
42820a708f8fSGustavo F. Padovan 
42830a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
42840a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4285b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4286e860d2c9SBen Seri 						   req, sizeof(req), &result);
42870a708f8fSGustavo F. Padovan 			if (len < 0) {
42885e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42890a708f8fSGustavo F. Padovan 				goto done;
42900a708f8fSGustavo F. Padovan 			}
42910a708f8fSGustavo F. Padovan 
42920a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
42930a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
429473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
42950a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
42960a708f8fSGustavo F. Padovan 				goto done;
42970a708f8fSGustavo F. Padovan 			break;
42980a708f8fSGustavo F. Padovan 		}
42996317950cSGustavo A. R. Silva 		/* fall through */
43000a708f8fSGustavo F. Padovan 
43010a708f8fSGustavo F. Padovan 	default:
43026be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
43032e0052e4SAndrei Emeltchenko 
4304ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
43055e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
43060a708f8fSGustavo F. Padovan 		goto done;
43070a708f8fSGustavo F. Padovan 	}
43080a708f8fSGustavo F. Padovan 
430959e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
43100a708f8fSGustavo F. Padovan 		goto done;
43110a708f8fSGustavo F. Padovan 
4312c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
43130a708f8fSGustavo F. Padovan 
4314c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
431547d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
43160a708f8fSGustavo F. Padovan 
4317105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4318105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
43193c588192SMat Martineau 			err = l2cap_ertm_init(chan);
43200a708f8fSGustavo F. Padovan 
43213c588192SMat Martineau 		if (err < 0)
43225e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
43233c588192SMat Martineau 		else
4324cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
43250a708f8fSGustavo F. Padovan 	}
43260a708f8fSGustavo F. Padovan 
43270a708f8fSGustavo F. Padovan done:
43286be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43293c588192SMat Martineau 	return err;
43300a708f8fSGustavo F. Padovan }
43310a708f8fSGustavo F. Padovan 
43322d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4333cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4334cb3b3152SJohan Hedberg 				       u8 *data)
43350a708f8fSGustavo F. Padovan {
43360a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
43370a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
43380a708f8fSGustavo F. Padovan 	u16 dcid, scid;
433948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43400a708f8fSGustavo F. Padovan 
4341cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4342cb3b3152SJohan Hedberg 		return -EPROTO;
4343cb3b3152SJohan Hedberg 
43440a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
43450a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
43460a708f8fSGustavo F. Padovan 
43470a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
43480a708f8fSGustavo F. Padovan 
43493df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43503df91ea2SAndrei Emeltchenko 
43513df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
43523df91ea2SAndrei Emeltchenko 	if (!chan) {
43533df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4354662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4355662d652dSJohan Hedberg 		return 0;
43563df91ea2SAndrei Emeltchenko 	}
43570a708f8fSGustavo F. Padovan 
43586be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
43596be36555SAndrei Emeltchenko 
4360fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4361fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
43620a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
43630a708f8fSGustavo F. Padovan 
43645ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
43650a708f8fSGustavo F. Padovan 
436661d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
436748454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
43686be36555SAndrei Emeltchenko 
43696be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43700a708f8fSGustavo F. Padovan 
437180b98027SGustavo Padovan 	chan->ops->close(chan);
437261d6ef3eSMat Martineau 	l2cap_chan_put(chan);
43733df91ea2SAndrei Emeltchenko 
43743df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43753df91ea2SAndrei Emeltchenko 
43760a708f8fSGustavo F. Padovan 	return 0;
43770a708f8fSGustavo F. Padovan }
43780a708f8fSGustavo F. Padovan 
43792d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4380cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4381cb3b3152SJohan Hedberg 				       u8 *data)
43820a708f8fSGustavo F. Padovan {
43830a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
43840a708f8fSGustavo F. Padovan 	u16 dcid, scid;
438548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43860a708f8fSGustavo F. Padovan 
4387cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4388cb3b3152SJohan Hedberg 		return -EPROTO;
4389cb3b3152SJohan Hedberg 
43900a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
43910a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
43940a708f8fSGustavo F. Padovan 
43953df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43963df91ea2SAndrei Emeltchenko 
43973df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
43983df91ea2SAndrei Emeltchenko 	if (!chan) {
43993df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
44000a708f8fSGustavo F. Padovan 		return 0;
44013df91ea2SAndrei Emeltchenko 	}
44020a708f8fSGustavo F. Padovan 
44036be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
440448454079SGustavo F. Padovan 
440528261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
440628261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
440728261da8SMatias Karhumaa 		mutex_unlock(&conn->chan_lock);
440828261da8SMatias Karhumaa 		return 0;
440928261da8SMatias Karhumaa 	}
441028261da8SMatias Karhumaa 
441161d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
441248454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
44136be36555SAndrei Emeltchenko 
44146be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44150a708f8fSGustavo F. Padovan 
441680b98027SGustavo Padovan 	chan->ops->close(chan);
441761d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44183df91ea2SAndrei Emeltchenko 
44193df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
44203df91ea2SAndrei Emeltchenko 
44210a708f8fSGustavo F. Padovan 	return 0;
44220a708f8fSGustavo F. Padovan }
44230a708f8fSGustavo F. Padovan 
44242d792818SGustavo Padovan static inline int l2cap_information_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_info_req *req = (struct l2cap_info_req *) data;
44290a708f8fSGustavo F. Padovan 	u16 type;
44300a708f8fSGustavo F. Padovan 
4431cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4432cb3b3152SJohan Hedberg 		return -EPROTO;
4433cb3b3152SJohan Hedberg 
44340a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
44350a708f8fSGustavo F. Padovan 
44360a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
44370a708f8fSGustavo F. Padovan 
44380a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
44390a708f8fSGustavo F. Padovan 		u8 buf[8];
44400a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
44410a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4442dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4443dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
44440a708f8fSGustavo F. Padovan 		if (!disable_ertm)
44450a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
44460a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
44470bd49fc7SJohan Hedberg 		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
44486327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
44496327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4450a5fd6f30SAndrei Emeltchenko 
44510a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
44522d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44532d792818SGustavo Padovan 			       buf);
44540a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
44550a708f8fSGustavo F. Padovan 		u8 buf[12];
44560a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
445750a147cdSMat Martineau 
4458dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4459dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
44600bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
44610bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
44622d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44632d792818SGustavo Padovan 			       buf);
44640a708f8fSGustavo F. Padovan 	} else {
44650a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
44660a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4467dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
44682d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
44692d792818SGustavo Padovan 			       &rsp);
44700a708f8fSGustavo F. Padovan 	}
44710a708f8fSGustavo F. Padovan 
44720a708f8fSGustavo F. Padovan 	return 0;
44730a708f8fSGustavo F. Padovan }
44740a708f8fSGustavo F. Padovan 
44752d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4476cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4477cb3b3152SJohan Hedberg 					u8 *data)
44780a708f8fSGustavo F. Padovan {
44790a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
44800a708f8fSGustavo F. Padovan 	u16 type, result;
44810a708f8fSGustavo F. Padovan 
44823f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4483cb3b3152SJohan Hedberg 		return -EPROTO;
4484cb3b3152SJohan Hedberg 
44850a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
44860a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
44870a708f8fSGustavo F. Padovan 
44880a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
44890a708f8fSGustavo F. Padovan 
4490e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4491e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4492e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4493e90165beSAndrei Emeltchenko 		return 0;
4494e90165beSAndrei Emeltchenko 
449517cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
44960a708f8fSGustavo F. Padovan 
44970a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
44980a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
44990a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
45000a708f8fSGustavo F. Padovan 
45010a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
45020a708f8fSGustavo F. Padovan 
45030a708f8fSGustavo F. Padovan 		return 0;
45040a708f8fSGustavo F. Padovan 	}
45050a708f8fSGustavo F. Padovan 
4506978c93b9SAndrei Emeltchenko 	switch (type) {
4507978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
45080a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
45090a708f8fSGustavo F. Padovan 
45100a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
45110a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4512dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
45130a708f8fSGustavo F. Padovan 
45140a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
45150a708f8fSGustavo F. Padovan 
45160a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
45170a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
45180a708f8fSGustavo F. Padovan 		} else {
45190a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45200a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
45210a708f8fSGustavo F. Padovan 
45220a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
45230a708f8fSGustavo F. Padovan 		}
4524978c93b9SAndrei Emeltchenko 		break;
4525978c93b9SAndrei Emeltchenko 
4526978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
45270bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
45280a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45290a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
45300a708f8fSGustavo F. Padovan 
45310a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4532978c93b9SAndrei Emeltchenko 		break;
45330a708f8fSGustavo F. Padovan 	}
45340a708f8fSGustavo F. Padovan 
45350a708f8fSGustavo F. Padovan 	return 0;
45360a708f8fSGustavo F. Padovan }
45370a708f8fSGustavo F. Padovan 
45381700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
45392d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
45402d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4541f94ff6ffSMat Martineau {
4542f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
45436e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
45441700915fSMat Martineau 	struct l2cap_chan *chan;
45456e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4546f94ff6ffSMat Martineau 	u16 psm, scid;
4547f94ff6ffSMat Martineau 
4548f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4549f94ff6ffSMat Martineau 		return -EPROTO;
4550f94ff6ffSMat Martineau 
45510bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4552f94ff6ffSMat Martineau 		return -EINVAL;
4553f94ff6ffSMat Martineau 
4554f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4555f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4556f94ff6ffSMat Martineau 
4557ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4558f94ff6ffSMat Martineau 
45596e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
45606ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
45616e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45626e1df6a6SAndrei Emeltchenko 			      req->amp_id);
45636e1df6a6SAndrei Emeltchenko 		return 0;
45646e1df6a6SAndrei Emeltchenko 	}
45651700915fSMat Martineau 
45661700915fSMat Martineau 	/* Validate AMP controller id */
45671700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
45686e1df6a6SAndrei Emeltchenko 	if (!hdev)
45696e1df6a6SAndrei Emeltchenko 		goto error;
45701700915fSMat Martineau 
45716e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
45726e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
45736e1df6a6SAndrei Emeltchenko 		goto error;
45746e1df6a6SAndrei Emeltchenko 	}
45756e1df6a6SAndrei Emeltchenko 
45766e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45776e1df6a6SAndrei Emeltchenko 			     req->amp_id);
45786e1df6a6SAndrei Emeltchenko 	if (chan) {
45796e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
45806e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
45816e1df6a6SAndrei Emeltchenko 
458298e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
458398e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
45846e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
45856e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4586662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4587662d652dSJohan Hedberg 					       chan->dcid);
4588662d652dSJohan Hedberg 			return 0;
45896e1df6a6SAndrei Emeltchenko 		}
45906e1df6a6SAndrei Emeltchenko 
45916e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
45926e1df6a6SAndrei Emeltchenko 
45936e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
45946e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4595fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
45966e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
45976e1df6a6SAndrei Emeltchenko 	}
45986e1df6a6SAndrei Emeltchenko 
45996e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
46006e1df6a6SAndrei Emeltchenko 
46016e1df6a6SAndrei Emeltchenko 	return 0;
46026e1df6a6SAndrei Emeltchenko 
46036e1df6a6SAndrei Emeltchenko error:
4604f94ff6ffSMat Martineau 	rsp.dcid = 0;
4605f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
4606dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
4607dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4608f94ff6ffSMat Martineau 
4609f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4610f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4611f94ff6ffSMat Martineau 
4612dc280801SJohan Hedberg 	return 0;
4613f94ff6ffSMat Martineau }
4614f94ff6ffSMat Martineau 
46158eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
46168eb200bdSMat Martineau {
46178eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
46188eb200bdSMat Martineau 	u8 ident;
46198eb200bdSMat Martineau 
46208eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
46218eb200bdSMat Martineau 
46228eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
46238eb200bdSMat Martineau 	chan->ident = ident;
46248eb200bdSMat Martineau 
46258eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
46268eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
46278eb200bdSMat Martineau 
46288eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
46298eb200bdSMat Martineau 		       &req);
46308eb200bdSMat Martineau 
46318eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
46328eb200bdSMat Martineau }
46338eb200bdSMat Martineau 
46341500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
46358d5a04a1SMat Martineau {
46368d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
46378d5a04a1SMat Martineau 
46381500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46398d5a04a1SMat Martineau 
46401500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
46418d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
46428d5a04a1SMat Martineau 
46431500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
46441500109bSMat Martineau 		       sizeof(rsp), &rsp);
46458d5a04a1SMat Martineau }
46468d5a04a1SMat Martineau 
46475b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
46488d5a04a1SMat Martineau {
46498d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46508d5a04a1SMat Martineau 
46515b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46528d5a04a1SMat Martineau 
46535b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
46548d5a04a1SMat Martineau 
46555b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
46568d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
46578d5a04a1SMat Martineau 
46585b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
46595b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46605b155ef9SMat Martineau 
46615b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
46625b155ef9SMat Martineau }
46635b155ef9SMat Martineau 
46645b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
46655b155ef9SMat Martineau {
46665b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46675b155ef9SMat Martineau 
46685b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
46695b155ef9SMat Martineau 
46705b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
4671dcf4adbfSJoe Perches 	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
46725b155ef9SMat Martineau 
46735b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
46745b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46758d5a04a1SMat Martineau }
46768d5a04a1SMat Martineau 
46778d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
46788d5a04a1SMat Martineau 					 u16 icid)
46798d5a04a1SMat Martineau {
46808d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
46818d5a04a1SMat Martineau 
4682ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
46838d5a04a1SMat Martineau 
46848d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
46858d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
46868d5a04a1SMat Martineau }
46878d5a04a1SMat Martineau 
46885f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
46895f3847a4SMat Martineau {
46905f3847a4SMat Martineau 	chan->hs_hchan = NULL;
46915f3847a4SMat Martineau 	chan->hs_hcon = NULL;
46925f3847a4SMat Martineau 
46935f3847a4SMat Martineau 	/* Placeholder - release the logical link */
46945f3847a4SMat Martineau }
46955f3847a4SMat Martineau 
46961500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
46971500109bSMat Martineau {
46981500109bSMat Martineau 	/* Logical link setup failed */
46991500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
47001500109bSMat Martineau 		/* Create channel failure, disconnect */
47015e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
47021500109bSMat Martineau 		return;
47031500109bSMat Martineau 	}
47041500109bSMat Martineau 
47051500109bSMat Martineau 	switch (chan->move_role) {
47061500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
47071500109bSMat Martineau 		l2cap_move_done(chan);
47081500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
47091500109bSMat Martineau 		break;
47101500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
47111500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
47121500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
47131500109bSMat Martineau 			/* Remote has only sent pending or
47141500109bSMat Martineau 			 * success responses, clean up
47151500109bSMat Martineau 			 */
47161500109bSMat Martineau 			l2cap_move_done(chan);
47171500109bSMat Martineau 		}
47181500109bSMat Martineau 
47191500109bSMat Martineau 		/* Other amp move states imply that the move
47201500109bSMat Martineau 		 * has already aborted
47211500109bSMat Martineau 		 */
47221500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
47231500109bSMat Martineau 		break;
47241500109bSMat Martineau 	}
47251500109bSMat Martineau }
47261500109bSMat Martineau 
47271500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
47281500109bSMat Martineau 					struct hci_chan *hchan)
47291500109bSMat Martineau {
47301500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
47311500109bSMat Martineau 
4732336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
47331500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
47341500109bSMat Martineau 
473535ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
47361500109bSMat Martineau 
47371500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4738fe79c6feSAndrei Emeltchenko 		int err;
47391500109bSMat Martineau 
47401500109bSMat Martineau 		set_default_fcs(chan);
47411500109bSMat Martineau 
47421500109bSMat Martineau 		err = l2cap_ertm_init(chan);
47431500109bSMat Martineau 		if (err < 0)
47445e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
47451500109bSMat Martineau 		else
47461500109bSMat Martineau 			l2cap_chan_ready(chan);
47471500109bSMat Martineau 	}
47481500109bSMat Martineau }
47491500109bSMat Martineau 
47501500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
47511500109bSMat Martineau 				      struct hci_chan *hchan)
47521500109bSMat Martineau {
47531500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
47541500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
47551500109bSMat Martineau 
47561500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
47571500109bSMat Martineau 
47581500109bSMat Martineau 	switch (chan->move_state) {
47591500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
47601500109bSMat Martineau 		/* Move confirm will be sent after a success
47611500109bSMat Martineau 		 * response is received
47621500109bSMat Martineau 		 */
47631500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
47641500109bSMat Martineau 		break;
47651500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
47661500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
47671500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
47681500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
47691500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
47701500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
47711500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
47721500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
47731500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
47741500109bSMat Martineau 		}
47751500109bSMat Martineau 		break;
47761500109bSMat Martineau 	default:
47771500109bSMat Martineau 		/* Move was not in expected state, free the channel */
47781500109bSMat Martineau 		__release_logical_link(chan);
47791500109bSMat Martineau 
47801500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
47811500109bSMat Martineau 	}
47821500109bSMat Martineau }
47831500109bSMat Martineau 
47841500109bSMat Martineau /* Call with chan locked */
478527695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
47865b155ef9SMat Martineau 		       u8 status)
47875b155ef9SMat Martineau {
47881500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
47891500109bSMat Martineau 
47901500109bSMat Martineau 	if (status) {
47911500109bSMat Martineau 		l2cap_logical_fail(chan);
47921500109bSMat Martineau 		__release_logical_link(chan);
47935b155ef9SMat Martineau 		return;
47945b155ef9SMat Martineau 	}
47955b155ef9SMat Martineau 
47961500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
47971500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
47986ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
47991500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
48001500109bSMat Martineau 	} else {
48011500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
48021500109bSMat Martineau 	}
48031500109bSMat Martineau }
48041500109bSMat Martineau 
48053f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
48063f7a56c4SMat Martineau {
48073f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
48083f7a56c4SMat Martineau 
48096ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
48103f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
48113f7a56c4SMat Martineau 			return;
48123f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
48133f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
48143f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
48153f7a56c4SMat Martineau 	} else {
48163f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
48173f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
48183f7a56c4SMat Martineau 		chan->move_id = 0;
48193f7a56c4SMat Martineau 		l2cap_move_setup(chan);
48203f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
48213f7a56c4SMat Martineau 	}
48223f7a56c4SMat Martineau }
48233f7a56c4SMat Martineau 
48248eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
48258eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
48268eb200bdSMat Martineau {
482762748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
482862748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
482962748ca1SAndrei Emeltchenko 
483012d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
483112d6cc60SAndrei Emeltchenko 
483262748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
483362748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
483462748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
483562748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
483662748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
483762748ca1SAndrei Emeltchenko 		} else {
483862748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
483962748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
484062748ca1SAndrei Emeltchenko 		}
484162748ca1SAndrei Emeltchenko 
484262748ca1SAndrei Emeltchenko 		return;
484362748ca1SAndrei Emeltchenko 	}
484462748ca1SAndrei Emeltchenko 
484562748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
484662748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
48478eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
48488eb200bdSMat Martineau 		char buf[128];
48498eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
48508eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
48518eb200bdSMat Martineau 
48528eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
48538eb200bdSMat Martineau 			/* Send successful response */
4854dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
4855dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
48568eb200bdSMat Martineau 		} else {
48578eb200bdSMat Martineau 			/* Send negative response */
4858dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
4859dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
48608eb200bdSMat Martineau 		}
48618eb200bdSMat Martineau 
48628eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
48638eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
48648eb200bdSMat Martineau 
48658eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4866f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
48678eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
48688eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
48698eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
4870e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
48718eb200bdSMat Martineau 			chan->num_conf_req++;
48728eb200bdSMat Martineau 		}
48738eb200bdSMat Martineau 	}
48748eb200bdSMat Martineau }
48758eb200bdSMat Martineau 
48768eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
48778eb200bdSMat Martineau 				   u8 remote_amp_id)
48788eb200bdSMat Martineau {
48798eb200bdSMat Martineau 	l2cap_move_setup(chan);
48808eb200bdSMat Martineau 	chan->move_id = local_amp_id;
48818eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
48828eb200bdSMat Martineau 
48838eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
48848eb200bdSMat Martineau }
48858eb200bdSMat Martineau 
48868eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
48878eb200bdSMat Martineau {
48888eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
48898eb200bdSMat Martineau 
48908eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
48918eb200bdSMat Martineau 
48928eb200bdSMat Martineau 	if (hchan) {
48938eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
48948eb200bdSMat Martineau 			/* Logical link is ready to go */
48958eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
48968eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
48978eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48988eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48998eb200bdSMat Martineau 
49008eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
49018eb200bdSMat Martineau 		} else {
49028eb200bdSMat Martineau 			/* Wait for logical link to be ready */
49038eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
49048eb200bdSMat Martineau 		}
49058eb200bdSMat Martineau 	} else {
49068eb200bdSMat Martineau 		/* Logical link not available */
49078eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
49088eb200bdSMat Martineau 	}
49098eb200bdSMat Martineau }
49108eb200bdSMat Martineau 
49118eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
49128eb200bdSMat Martineau {
49138eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
49148eb200bdSMat Martineau 		u8 rsp_result;
49158eb200bdSMat Martineau 		if (result == -EINVAL)
49168eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
49178eb200bdSMat Martineau 		else
49188eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
49198eb200bdSMat Martineau 
49208eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
49218eb200bdSMat Martineau 	}
49228eb200bdSMat Martineau 
49238eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
49248eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
49258eb200bdSMat Martineau 
49268eb200bdSMat Martineau 	/* Restart data transmission */
49278eb200bdSMat Martineau 	l2cap_ertm_send(chan);
49288eb200bdSMat Martineau }
49298eb200bdSMat Martineau 
4930a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
4931a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
49328eb200bdSMat Martineau {
4933770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
4934fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
4935770bfefaSAndrei Emeltchenko 
49368eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
49378eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
49388eb200bdSMat Martineau 
4939df66499aSDan Carpenter 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED)
49408eb200bdSMat Martineau 		return;
49418eb200bdSMat Martineau 
49428eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
49438eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
49448eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
49458eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
49468eb200bdSMat Martineau 	} else {
49478eb200bdSMat Martineau 		switch (chan->move_role) {
49488eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
49498eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
49508eb200bdSMat Martineau 					       remote_amp_id);
49518eb200bdSMat Martineau 			break;
49528eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
49538eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
49548eb200bdSMat Martineau 			break;
49558eb200bdSMat Martineau 		default:
49568eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
49578eb200bdSMat Martineau 			break;
49588eb200bdSMat Martineau 		}
49598eb200bdSMat Martineau 	}
49608eb200bdSMat Martineau }
49618eb200bdSMat Martineau 
49628d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
4963ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
4964ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
49658d5a04a1SMat Martineau {
49668d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
49671500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
496802b0fbb9SMat Martineau 	struct l2cap_chan *chan;
49698d5a04a1SMat Martineau 	u16 icid = 0;
49708d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
49718d5a04a1SMat Martineau 
49728d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
49738d5a04a1SMat Martineau 		return -EPROTO;
49748d5a04a1SMat Martineau 
49758d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
49768d5a04a1SMat Martineau 
4977ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
49788d5a04a1SMat Martineau 
49790bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
49808d5a04a1SMat Martineau 		return -EINVAL;
49818d5a04a1SMat Martineau 
498202b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
498302b0fbb9SMat Martineau 	if (!chan) {
49841500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
4985dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
49861500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
49871500109bSMat Martineau 			       sizeof(rsp), &rsp);
498802b0fbb9SMat Martineau 		return 0;
498902b0fbb9SMat Martineau 	}
499002b0fbb9SMat Martineau 
49911500109bSMat Martineau 	chan->ident = cmd->ident;
49921500109bSMat Martineau 
499302b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
499402b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
499502b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
499602b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
499702b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
499802b0fbb9SMat Martineau 		goto send_move_response;
499902b0fbb9SMat Martineau 	}
500002b0fbb9SMat Martineau 
500102b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
500202b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
500302b0fbb9SMat Martineau 		goto send_move_response;
500402b0fbb9SMat Martineau 	}
500502b0fbb9SMat Martineau 
50066ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
500702b0fbb9SMat Martineau 		struct hci_dev *hdev;
500802b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
500902b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
501002b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
501102b0fbb9SMat Martineau 			if (hdev)
501202b0fbb9SMat Martineau 				hci_dev_put(hdev);
501302b0fbb9SMat Martineau 
501402b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
501502b0fbb9SMat Martineau 			goto send_move_response;
501602b0fbb9SMat Martineau 		}
501702b0fbb9SMat Martineau 		hci_dev_put(hdev);
501802b0fbb9SMat Martineau 	}
501902b0fbb9SMat Martineau 
502002b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
502102b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
502202b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
502302b0fbb9SMat Martineau 	 */
502402b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
502502b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
50266f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
502702b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
502802b0fbb9SMat Martineau 		goto send_move_response;
502902b0fbb9SMat Martineau 	}
503002b0fbb9SMat Martineau 
503102b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
503202b0fbb9SMat Martineau 	l2cap_move_setup(chan);
503302b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
503402b0fbb9SMat Martineau 	icid = chan->dcid;
503502b0fbb9SMat Martineau 
50366ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
503702b0fbb9SMat Martineau 		/* Moving to BR/EDR */
503802b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
503902b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
504002b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
504102b0fbb9SMat Martineau 		} else {
504202b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
504302b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
504402b0fbb9SMat Martineau 		}
504502b0fbb9SMat Martineau 	} else {
504602b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
504702b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
504802b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
504902b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
505002b0fbb9SMat Martineau 	}
505102b0fbb9SMat Martineau 
505202b0fbb9SMat Martineau send_move_response:
50531500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
50548d5a04a1SMat Martineau 
505502b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
505602b0fbb9SMat Martineau 
50578d5a04a1SMat Martineau 	return 0;
50588d5a04a1SMat Martineau }
50598d5a04a1SMat Martineau 
50605b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
50615b155ef9SMat Martineau {
50625b155ef9SMat Martineau 	struct l2cap_chan *chan;
50635b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
50645b155ef9SMat Martineau 
50655b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
50665b155ef9SMat Martineau 	if (!chan) {
50675b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
50685b155ef9SMat Martineau 		return;
50695b155ef9SMat Martineau 	}
50705b155ef9SMat Martineau 
50715b155ef9SMat Martineau 	__clear_chan_timer(chan);
50725b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
50735b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
50745b155ef9SMat Martineau 
50755b155ef9SMat Martineau 	switch (chan->move_state) {
50765b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50775b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
50785b155ef9SMat Martineau 		 * is complete.
50795b155ef9SMat Martineau 		 */
50805b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50815b155ef9SMat Martineau 		break;
50825b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
50835b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
50845b155ef9SMat Martineau 			break;
50855b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
50865b155ef9SMat Martineau 				    &chan->conn_state)) {
50875b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50885b155ef9SMat Martineau 		} else {
50895b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
50905b155ef9SMat Martineau 			 * proceed with move
50915b155ef9SMat Martineau 			 */
50925b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50935b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50945b155ef9SMat Martineau 		}
50955b155ef9SMat Martineau 		break;
50965b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
50975b155ef9SMat Martineau 		/* Moving to AMP */
50985b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
50995b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
51005b155ef9SMat Martineau 			 * after logical link is ready
51015b155ef9SMat Martineau 			 */
51025b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51035b155ef9SMat Martineau 		} else {
51045b155ef9SMat Martineau 			/* Both logical link and move success
51055b155ef9SMat Martineau 			 * are required to confirm
51065b155ef9SMat Martineau 			 */
51075b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
51085b155ef9SMat Martineau 		}
51095b155ef9SMat Martineau 
51105b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
51115b155ef9SMat Martineau 		if (!hchan) {
51125b155ef9SMat Martineau 			/* Logical link not available */
51135b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51145b155ef9SMat Martineau 			break;
51155b155ef9SMat Martineau 		}
51165b155ef9SMat Martineau 
51175b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
51185b155ef9SMat Martineau 		 * send confirmation.
51195b155ef9SMat Martineau 		 */
51205b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
51215b155ef9SMat Martineau 			break;
51225b155ef9SMat Martineau 
51235b155ef9SMat Martineau 		/* Logical link is already ready to go */
51245b155ef9SMat Martineau 
51255b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
51265b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
51275b155ef9SMat Martineau 
51285b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
51295b155ef9SMat Martineau 			/* Can confirm now */
51305b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
51315b155ef9SMat Martineau 		} else {
51325b155ef9SMat Martineau 			/* Now only need move success
51335b155ef9SMat Martineau 			 * to confirm
51345b155ef9SMat Martineau 			 */
51355b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
51365b155ef9SMat Martineau 		}
51375b155ef9SMat Martineau 
51385b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
51395b155ef9SMat Martineau 		break;
51405b155ef9SMat Martineau 	default:
51415b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
51425b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
51435b155ef9SMat Martineau 		l2cap_move_done(chan);
51445b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51455b155ef9SMat Martineau 	}
51465b155ef9SMat Martineau 
51475b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51485b155ef9SMat Martineau }
51495b155ef9SMat Martineau 
51505b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
51515b155ef9SMat Martineau 			    u16 result)
51525b155ef9SMat Martineau {
51535b155ef9SMat Martineau 	struct l2cap_chan *chan;
51545b155ef9SMat Martineau 
51555b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
51565b155ef9SMat Martineau 	if (!chan) {
51575b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
51585b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51595b155ef9SMat Martineau 		return;
51605b155ef9SMat Martineau 	}
51615b155ef9SMat Martineau 
51625b155ef9SMat Martineau 	__clear_chan_timer(chan);
51635b155ef9SMat Martineau 
51645b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
51655b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
51665b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
51675b155ef9SMat Martineau 		} else {
51685b155ef9SMat Martineau 			/* Cleanup - cancel move */
51695b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
51705b155ef9SMat Martineau 			l2cap_move_done(chan);
51715b155ef9SMat Martineau 		}
51725b155ef9SMat Martineau 	}
51735b155ef9SMat Martineau 
51745b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51755b155ef9SMat Martineau 
51765b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51775b155ef9SMat Martineau }
51785b155ef9SMat Martineau 
51795b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5180ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5181ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
51828d5a04a1SMat Martineau {
51838d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
51848d5a04a1SMat Martineau 	u16 icid, result;
51858d5a04a1SMat Martineau 
51868d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
51878d5a04a1SMat Martineau 		return -EPROTO;
51888d5a04a1SMat Martineau 
51898d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
51908d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
51918d5a04a1SMat Martineau 
5192ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
51938d5a04a1SMat Martineau 
51945b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
51955b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
51965b155ef9SMat Martineau 	else
51975b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
51988d5a04a1SMat Martineau 
51998d5a04a1SMat Martineau 	return 0;
52008d5a04a1SMat Martineau }
52018d5a04a1SMat Martineau 
52025f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5203ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5204ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
52058d5a04a1SMat Martineau {
52068d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
52075f3847a4SMat Martineau 	struct l2cap_chan *chan;
52088d5a04a1SMat Martineau 	u16 icid, result;
52098d5a04a1SMat Martineau 
52108d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
52118d5a04a1SMat Martineau 		return -EPROTO;
52128d5a04a1SMat Martineau 
52138d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
52148d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
52158d5a04a1SMat Martineau 
5216ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
52178d5a04a1SMat Martineau 
52185f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
52195f3847a4SMat Martineau 	if (!chan) {
52205f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
52218d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
52225f3847a4SMat Martineau 		return 0;
52235f3847a4SMat Martineau 	}
52245f3847a4SMat Martineau 
52255f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
52265f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
52275f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
52286ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
52295f3847a4SMat Martineau 				__release_logical_link(chan);
52305f3847a4SMat Martineau 		} else {
52315f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
52325f3847a4SMat Martineau 		}
52335f3847a4SMat Martineau 
52345f3847a4SMat Martineau 		l2cap_move_done(chan);
52355f3847a4SMat Martineau 	}
52365f3847a4SMat Martineau 
52375f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
52385f3847a4SMat Martineau 
52395f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
52408d5a04a1SMat Martineau 
52418d5a04a1SMat Martineau 	return 0;
52428d5a04a1SMat Martineau }
52438d5a04a1SMat Martineau 
52448d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5245ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5246ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
52478d5a04a1SMat Martineau {
52488d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
52493fd71a0aSMat Martineau 	struct l2cap_chan *chan;
52508d5a04a1SMat Martineau 	u16 icid;
52518d5a04a1SMat Martineau 
52528d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
52538d5a04a1SMat Martineau 		return -EPROTO;
52548d5a04a1SMat Martineau 
52558d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
52568d5a04a1SMat Martineau 
5257ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
52588d5a04a1SMat Martineau 
52593fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
52603fd71a0aSMat Martineau 	if (!chan)
52613fd71a0aSMat Martineau 		return 0;
52623fd71a0aSMat Martineau 
52633fd71a0aSMat Martineau 	__clear_chan_timer(chan);
52643fd71a0aSMat Martineau 
52653fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
52663fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
52673fd71a0aSMat Martineau 
52686ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
52693fd71a0aSMat Martineau 			__release_logical_link(chan);
52703fd71a0aSMat Martineau 
52713fd71a0aSMat Martineau 		l2cap_move_done(chan);
52723fd71a0aSMat Martineau 	}
52733fd71a0aSMat Martineau 
52743fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
52753fd71a0aSMat Martineau 
52768d5a04a1SMat Martineau 	return 0;
52778d5a04a1SMat Martineau }
52788d5a04a1SMat Martineau 
5279de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
52802d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5281203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5282de73115aSClaudio Takahasi {
5283de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5284de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5285de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5286203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
52872ce603ebSClaudio Takahasi 	int err;
5288de73115aSClaudio Takahasi 
528940bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
5290de73115aSClaudio Takahasi 		return -EINVAL;
5291de73115aSClaudio Takahasi 
5292de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5293de73115aSClaudio Takahasi 		return -EPROTO;
5294de73115aSClaudio Takahasi 
5295de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5296de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5297de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5298de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5299de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5300de73115aSClaudio Takahasi 
5301de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5302de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5303de73115aSClaudio Takahasi 
5304de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
53052ce603ebSClaudio Takahasi 
5306d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
53072ce603ebSClaudio Takahasi 	if (err)
5308dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5309de73115aSClaudio Takahasi 	else
5310dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5311de73115aSClaudio Takahasi 
5312de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5313de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5314de73115aSClaudio Takahasi 
5315ffb5a827SAndre Guedes 	if (!err) {
5316f4869e2aSJohan Hedberg 		u8 store_hint;
5317ffb5a827SAndre Guedes 
5318f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
5319f4869e2aSJohan Hedberg 						to_multiplier);
5320f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
5321f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
5322f4869e2aSJohan Hedberg 				    to_multiplier);
5323f4869e2aSJohan Hedberg 
5324ffb5a827SAndre Guedes 	}
53252ce603ebSClaudio Takahasi 
5326de73115aSClaudio Takahasi 	return 0;
5327de73115aSClaudio Takahasi }
5328de73115aSClaudio Takahasi 
5329f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5330f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5331f1496deeSJohan Hedberg 				u8 *data)
5332f1496deeSJohan Hedberg {
5333f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
53343e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
5335f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5336f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
53373e64b7bdSJohan Hedberg 	int err, sec_level;
5338f1496deeSJohan Hedberg 
5339f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5340f1496deeSJohan Hedberg 		return -EPROTO;
5341f1496deeSJohan Hedberg 
5342f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5343f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5344f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5345f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5346f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5347f1496deeSJohan Hedberg 
5348571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
534940624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
535040624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
5351f1496deeSJohan Hedberg 		return -EPROTO;
5352f1496deeSJohan Hedberg 
5353f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5354f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5355f1496deeSJohan Hedberg 
5356f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5357f1496deeSJohan Hedberg 
5358f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5359f1496deeSJohan Hedberg 	if (!chan) {
5360f1496deeSJohan Hedberg 		err = -EBADSLT;
5361f1496deeSJohan Hedberg 		goto unlock;
5362f1496deeSJohan Hedberg 	}
5363f1496deeSJohan Hedberg 
5364f1496deeSJohan Hedberg 	err = 0;
5365f1496deeSJohan Hedberg 
5366f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5367f1496deeSJohan Hedberg 
5368f1496deeSJohan Hedberg 	switch (result) {
5369571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
537040624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
537140624183SJohan Hedberg 			err = -EBADSLT;
537240624183SJohan Hedberg 			break;
537340624183SJohan Hedberg 		}
537440624183SJohan Hedberg 
5375f1496deeSJohan Hedberg 		chan->ident = 0;
5376f1496deeSJohan Hedberg 		chan->dcid = dcid;
5377f1496deeSJohan Hedberg 		chan->omtu = mtu;
5378f1496deeSJohan Hedberg 		chan->remote_mps = mps;
53790cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5380f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5381f1496deeSJohan Hedberg 		break;
5382f1496deeSJohan Hedberg 
5383571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
5384571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
53853e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
53863e64b7bdSJohan Hedberg 		 * anything.
53873e64b7bdSJohan Hedberg 		 */
53883e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
53893e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
53903e64b7bdSJohan Hedberg 			break;
53913e64b7bdSJohan Hedberg 		}
53923e64b7bdSJohan Hedberg 
53933e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
53943e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
53953e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
53963e64b7bdSJohan Hedberg 
53973e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
53983e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
53993e64b7bdSJohan Hedberg 
54003e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
54013e64b7bdSJohan Hedberg 		break;
54023e64b7bdSJohan Hedberg 
5403f1496deeSJohan Hedberg 	default:
5404f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5405f1496deeSJohan Hedberg 		break;
5406f1496deeSJohan Hedberg 	}
5407f1496deeSJohan Hedberg 
5408f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5409f1496deeSJohan Hedberg 
5410f1496deeSJohan Hedberg unlock:
5411f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5412f1496deeSJohan Hedberg 
5413f1496deeSJohan Hedberg 	return err;
5414f1496deeSJohan Hedberg }
5415f1496deeSJohan Hedberg 
54163300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
54172d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
54182d792818SGustavo Padovan 				      u8 *data)
54193300d9a9SClaudio Takahasi {
54203300d9a9SClaudio Takahasi 	int err = 0;
54213300d9a9SClaudio Takahasi 
54223300d9a9SClaudio Takahasi 	switch (cmd->code) {
54233300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5424cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
54253300d9a9SClaudio Takahasi 		break;
54263300d9a9SClaudio Takahasi 
54273300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5428cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
54293300d9a9SClaudio Takahasi 		break;
54303300d9a9SClaudio Takahasi 
54313300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5432f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
54339245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
54343300d9a9SClaudio Takahasi 		break;
54353300d9a9SClaudio Takahasi 
54363300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
54373300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
54383300d9a9SClaudio Takahasi 		break;
54393300d9a9SClaudio Takahasi 
54403300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
54419245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
54423300d9a9SClaudio Takahasi 		break;
54433300d9a9SClaudio Takahasi 
54443300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5445cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
54463300d9a9SClaudio Takahasi 		break;
54473300d9a9SClaudio Takahasi 
54483300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
54499245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
54503300d9a9SClaudio Takahasi 		break;
54513300d9a9SClaudio Takahasi 
54523300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
54533300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
54543300d9a9SClaudio Takahasi 		break;
54553300d9a9SClaudio Takahasi 
54563300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
54573300d9a9SClaudio Takahasi 		break;
54583300d9a9SClaudio Takahasi 
54593300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5460cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
54613300d9a9SClaudio Takahasi 		break;
54623300d9a9SClaudio Takahasi 
54633300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
54649245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
54653300d9a9SClaudio Takahasi 		break;
54663300d9a9SClaudio Takahasi 
5467f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5468f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5469f94ff6ffSMat Martineau 		break;
5470f94ff6ffSMat Martineau 
54718d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
54728d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
54738d5a04a1SMat Martineau 		break;
54748d5a04a1SMat Martineau 
54758d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
54769245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
54778d5a04a1SMat Martineau 		break;
54788d5a04a1SMat Martineau 
54798d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
54808d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
54818d5a04a1SMat Martineau 		break;
54828d5a04a1SMat Martineau 
54838d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
54849245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
54858d5a04a1SMat Martineau 		break;
54868d5a04a1SMat Martineau 
54873300d9a9SClaudio Takahasi 	default:
54883300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
54893300d9a9SClaudio Takahasi 		err = -EINVAL;
54903300d9a9SClaudio Takahasi 		break;
54913300d9a9SClaudio Takahasi 	}
54923300d9a9SClaudio Takahasi 
54933300d9a9SClaudio Takahasi 	return err;
54943300d9a9SClaudio Takahasi }
54953300d9a9SClaudio Takahasi 
549627e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
549727e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
549827e2d4c8SJohan Hedberg 				u8 *data)
549927e2d4c8SJohan Hedberg {
550027e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
550127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
550227e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
55030cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
550427e2d4c8SJohan Hedberg 	__le16 psm;
550527e2d4c8SJohan Hedberg 	u8 result;
550627e2d4c8SJohan Hedberg 
550727e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
550827e2d4c8SJohan Hedberg 		return -EPROTO;
550927e2d4c8SJohan Hedberg 
551027e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
551127e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
551227e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
551327e2d4c8SJohan Hedberg 	psm  = req->psm;
551427e2d4c8SJohan Hedberg 	dcid = 0;
55150cd75f7eSJohan Hedberg 	credits = 0;
551627e2d4c8SJohan Hedberg 
551727e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
551827e2d4c8SJohan Hedberg 		return -EPROTO;
551927e2d4c8SJohan Hedberg 
552027e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
552127e2d4c8SJohan Hedberg 	       scid, mtu, mps);
552227e2d4c8SJohan Hedberg 
552327e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
552427e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
552527e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
552627e2d4c8SJohan Hedberg 	if (!pchan) {
5527571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
552827e2d4c8SJohan Hedberg 		chan = NULL;
552927e2d4c8SJohan Hedberg 		goto response;
553027e2d4c8SJohan Hedberg 	}
553127e2d4c8SJohan Hedberg 
553227e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
553327e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
553427e2d4c8SJohan Hedberg 
553535dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
553635dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
5537571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
553827e2d4c8SJohan Hedberg 		chan = NULL;
553927e2d4c8SJohan Hedberg 		goto response_unlock;
554027e2d4c8SJohan Hedberg 	}
554127e2d4c8SJohan Hedberg 
55428a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
55438a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
5544571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
55458a7889ccSJohan Hedberg 		chan = NULL;
55468a7889ccSJohan Hedberg 		goto response_unlock;
55478a7889ccSJohan Hedberg 	}
55488a7889ccSJohan Hedberg 
554927e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
555027e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
5551571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
555227e2d4c8SJohan Hedberg 		chan = NULL;
555327e2d4c8SJohan Hedberg 		goto response_unlock;
555427e2d4c8SJohan Hedberg 	}
555527e2d4c8SJohan Hedberg 
555627e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
555727e2d4c8SJohan Hedberg 	if (!chan) {
5558571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
555927e2d4c8SJohan Hedberg 		goto response_unlock;
556027e2d4c8SJohan Hedberg 	}
556127e2d4c8SJohan Hedberg 
556227e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
556327e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
5564a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
5565a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
556627e2d4c8SJohan Hedberg 	chan->psm  = psm;
556727e2d4c8SJohan Hedberg 	chan->dcid = scid;
556827e2d4c8SJohan Hedberg 	chan->omtu = mtu;
556927e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
557027e2d4c8SJohan Hedberg 
557127e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
5572fe149310SLuiz Augusto von Dentz 
5573ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
5574fe149310SLuiz Augusto von Dentz 
557527e2d4c8SJohan Hedberg 	dcid = chan->scid;
55760cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
557727e2d4c8SJohan Hedberg 
557827e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
557927e2d4c8SJohan Hedberg 
558027e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
558127e2d4c8SJohan Hedberg 
558227e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
558327e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
5584434714dcSJohan Hedberg 		/* The following result value is actually not defined
5585434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
5586434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
5587434714dcSJohan Hedberg 		 * instead of sending a response.
5588434714dcSJohan Hedberg 		 */
558927e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
559027e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
559127e2d4c8SJohan Hedberg 	} else {
559227e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
5593571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
559427e2d4c8SJohan Hedberg 	}
559527e2d4c8SJohan Hedberg 
559627e2d4c8SJohan Hedberg response_unlock:
559727e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
559827e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5599a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
560027e2d4c8SJohan Hedberg 
560127e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
560227e2d4c8SJohan Hedberg 		return 0;
560327e2d4c8SJohan Hedberg 
560427e2d4c8SJohan Hedberg response:
560527e2d4c8SJohan Hedberg 	if (chan) {
560627e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
56073916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
560827e2d4c8SJohan Hedberg 	} else {
560927e2d4c8SJohan Hedberg 		rsp.mtu = 0;
561027e2d4c8SJohan Hedberg 		rsp.mps = 0;
561127e2d4c8SJohan Hedberg 	}
561227e2d4c8SJohan Hedberg 
561327e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
56140cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
561527e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
561627e2d4c8SJohan Hedberg 
561727e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
561827e2d4c8SJohan Hedberg 
561927e2d4c8SJohan Hedberg 	return 0;
562027e2d4c8SJohan Hedberg }
562127e2d4c8SJohan Hedberg 
5622fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5623fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5624fad5fc89SJohan Hedberg 				   u8 *data)
5625fad5fc89SJohan Hedberg {
5626fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5627fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
56280f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
5629fad5fc89SJohan Hedberg 
5630fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5631fad5fc89SJohan Hedberg 		return -EPROTO;
5632fad5fc89SJohan Hedberg 
5633fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5634fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5635fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5636fad5fc89SJohan Hedberg 
5637fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5638fad5fc89SJohan Hedberg 
5639fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5640fad5fc89SJohan Hedberg 	if (!chan)
5641fad5fc89SJohan Hedberg 		return -EBADSLT;
5642fad5fc89SJohan Hedberg 
56430f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
56440f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
56450f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
56460f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
5647ee93053dSMartin Townsend 		l2cap_chan_unlock(chan);
56480f1bfe4eSJohan Hedberg 
56490f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
56500f1bfe4eSJohan Hedberg 		 * command reject packet.
56510f1bfe4eSJohan Hedberg 		 */
56520f1bfe4eSJohan Hedberg 		return 0;
56530f1bfe4eSJohan Hedberg 	}
56540f1bfe4eSJohan Hedberg 
5655fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5656fad5fc89SJohan Hedberg 
56578a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
56588a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
5659fad5fc89SJohan Hedberg 
5660fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5661fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5662fad5fc89SJohan Hedberg 
5663fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5664fad5fc89SJohan Hedberg 
5665fad5fc89SJohan Hedberg 	return 0;
5666fad5fc89SJohan Hedberg }
5667fad5fc89SJohan Hedberg 
566871fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
566971fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
567071fb4197SJohan Hedberg 				       u8 *data)
567171fb4197SJohan Hedberg {
567271fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
567371fb4197SJohan Hedberg 	struct l2cap_chan *chan;
567471fb4197SJohan Hedberg 
567571fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
567671fb4197SJohan Hedberg 		return -EPROTO;
567771fb4197SJohan Hedberg 
567871fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
567971fb4197SJohan Hedberg 
568071fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
568171fb4197SJohan Hedberg 	if (!chan)
568271fb4197SJohan Hedberg 		goto done;
568371fb4197SJohan Hedberg 
568471fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
568571fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
568671fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
568771fb4197SJohan Hedberg 
568871fb4197SJohan Hedberg done:
568971fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
569071fb4197SJohan Hedberg 	return 0;
569171fb4197SJohan Hedberg }
569271fb4197SJohan Hedberg 
56933300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5694203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5695203e639eSJohan Hedberg 				   u8 *data)
56963300d9a9SClaudio Takahasi {
5697b5ecba64SJohan Hedberg 	int err = 0;
5698b5ecba64SJohan Hedberg 
56993300d9a9SClaudio Takahasi 	switch (cmd->code) {
57003300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
570171fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
5702b5ecba64SJohan Hedberg 		break;
57033300d9a9SClaudio Takahasi 
57043300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5705b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5706b5ecba64SJohan Hedberg 		break;
57073300d9a9SClaudio Takahasi 
57083300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5709b5ecba64SJohan Hedberg 		break;
57103300d9a9SClaudio Takahasi 
5711f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5712f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5713b5ecba64SJohan Hedberg 		break;
5714f1496deeSJohan Hedberg 
571527e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5716b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5717b5ecba64SJohan Hedberg 		break;
571827e2d4c8SJohan Hedberg 
5719fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5720fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5721fad5fc89SJohan Hedberg 		break;
5722fad5fc89SJohan Hedberg 
57233defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5724b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5725b5ecba64SJohan Hedberg 		break;
57263defe01aSJohan Hedberg 
57273defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
57283defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5729b5ecba64SJohan Hedberg 		break;
57303defe01aSJohan Hedberg 
57313300d9a9SClaudio Takahasi 	default:
57323300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5733b5ecba64SJohan Hedberg 		err = -EINVAL;
5734b5ecba64SJohan Hedberg 		break;
57353300d9a9SClaudio Takahasi 	}
5736b5ecba64SJohan Hedberg 
5737b5ecba64SJohan Hedberg 	return err;
57383300d9a9SClaudio Takahasi }
57393300d9a9SClaudio Takahasi 
5740c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5741c5623556SJohan Hedberg 					struct sk_buff *skb)
5742c5623556SJohan Hedberg {
574369c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
57444f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
57454f3e219dSMarcel Holtmann 	u16 len;
5746c5623556SJohan Hedberg 	int err;
5747c5623556SJohan Hedberg 
574869c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
57493b166295SMarcel Holtmann 		goto drop;
575069c4e4e8SJohan Hedberg 
57514f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
57524f3e219dSMarcel Holtmann 		goto drop;
5753c5623556SJohan Hedberg 
57544f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
57554f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5756c5623556SJohan Hedberg 
57574f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5758c5623556SJohan Hedberg 
57594f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
57604f3e219dSMarcel Holtmann 
57614f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5762c5623556SJohan Hedberg 		BT_DBG("corrupted command");
57634f3e219dSMarcel Holtmann 		goto drop;
5764c5623556SJohan Hedberg 	}
5765c5623556SJohan Hedberg 
5766203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5767c5623556SJohan Hedberg 	if (err) {
5768c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5769c5623556SJohan Hedberg 
5770c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5771c5623556SJohan Hedberg 
5772dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
57734f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5774c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5775c5623556SJohan Hedberg 	}
5776c5623556SJohan Hedberg 
57773b166295SMarcel Holtmann drop:
5778c5623556SJohan Hedberg 	kfree_skb(skb);
5779c5623556SJohan Hedberg }
5780c5623556SJohan Hedberg 
57813300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
57823300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
57830a708f8fSGustavo F. Padovan {
578469c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
57850a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
57860a708f8fSGustavo F. Padovan 	int len = skb->len;
57870a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
57883300d9a9SClaudio Takahasi 	int err;
57890a708f8fSGustavo F. Padovan 
57900a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
57910a708f8fSGustavo F. Padovan 
579269c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
57933b166295SMarcel Holtmann 		goto drop;
579469c4e4e8SJohan Hedberg 
57950a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
57960a708f8fSGustavo F. Padovan 		u16 cmd_len;
57970a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
57980a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
57990a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
58000a708f8fSGustavo F. Padovan 
58010a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
58020a708f8fSGustavo F. Padovan 
58032d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
58042d792818SGustavo Padovan 		       cmd.ident);
58050a708f8fSGustavo F. Padovan 
58060a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
58070a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
58080a708f8fSGustavo F. Padovan 			break;
58090a708f8fSGustavo F. Padovan 		}
58100a708f8fSGustavo F. Padovan 
58113300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
58120a708f8fSGustavo F. Padovan 		if (err) {
5813e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
58142c6d1a2eSGustavo F. Padovan 
58152c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
58160a708f8fSGustavo F. Padovan 
5817dcf4adbfSJoe Perches 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58182d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
58192d792818SGustavo Padovan 				       sizeof(rej), &rej);
58200a708f8fSGustavo F. Padovan 		}
58210a708f8fSGustavo F. Padovan 
58220a708f8fSGustavo F. Padovan 		data += cmd_len;
58230a708f8fSGustavo F. Padovan 		len  -= cmd_len;
58240a708f8fSGustavo F. Padovan 	}
58250a708f8fSGustavo F. Padovan 
58263b166295SMarcel Holtmann drop:
58270a708f8fSGustavo F. Padovan 	kfree_skb(skb);
58280a708f8fSGustavo F. Padovan }
58290a708f8fSGustavo F. Padovan 
583047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
58310a708f8fSGustavo F. Padovan {
58320a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5833e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5834e4ca6d98SAndrei Emeltchenko 
5835e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5836e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5837e4ca6d98SAndrei Emeltchenko 	else
5838e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
58390a708f8fSGustavo F. Padovan 
584047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
584103a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
58420a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
58430a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
58440a708f8fSGustavo F. Padovan 
58450a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
58460a708f8fSGustavo F. Padovan 			return -EBADMSG;
58470a708f8fSGustavo F. Padovan 	}
58480a708f8fSGustavo F. Padovan 	return 0;
58490a708f8fSGustavo F. Padovan }
58500a708f8fSGustavo F. Padovan 
58516ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
58520a708f8fSGustavo F. Padovan {
5853e31f7633SMat Martineau 	struct l2cap_ctrl control;
58540a708f8fSGustavo F. Padovan 
5855e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
58560a708f8fSGustavo F. Padovan 
5857e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5858e31f7633SMat Martineau 	control.sframe = 1;
5859e31f7633SMat Martineau 	control.final = 1;
5860e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5861e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
58620a708f8fSGustavo F. Padovan 
5863e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5864e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5865e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
58660a708f8fSGustavo F. Padovan 	}
58670a708f8fSGustavo F. Padovan 
5868e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5869e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5870e31f7633SMat Martineau 		__set_retrans_timer(chan);
58710a708f8fSGustavo F. Padovan 
5872e31f7633SMat Martineau 	/* Send pending iframes */
5873525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
58740a708f8fSGustavo F. Padovan 
5875e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5876e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5877e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5878e31f7633SMat Martineau 		 * send it now.
5879e31f7633SMat Martineau 		 */
5880e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5881e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
58820a708f8fSGustavo F. Padovan 	}
58830a708f8fSGustavo F. Padovan }
58840a708f8fSGustavo F. Padovan 
58852d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
58862d792818SGustavo Padovan 			    struct sk_buff **last_frag)
58870a708f8fSGustavo F. Padovan {
588884084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
588984084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
589084084a31SMat Martineau 	 */
589184084a31SMat Martineau 	if (!skb_has_frag_list(skb))
589284084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
589384084a31SMat Martineau 
589484084a31SMat Martineau 	new_frag->next = NULL;
589584084a31SMat Martineau 
589684084a31SMat Martineau 	(*last_frag)->next = new_frag;
589784084a31SMat Martineau 	*last_frag = new_frag;
589884084a31SMat Martineau 
589984084a31SMat Martineau 	skb->len += new_frag->len;
590084084a31SMat Martineau 	skb->data_len += new_frag->len;
590184084a31SMat Martineau 	skb->truesize += new_frag->truesize;
590284084a31SMat Martineau }
590384084a31SMat Martineau 
59044b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
59054b51dae9SMat Martineau 				struct l2cap_ctrl *control)
590684084a31SMat Martineau {
590784084a31SMat Martineau 	int err = -EINVAL;
59080a708f8fSGustavo F. Padovan 
59094b51dae9SMat Martineau 	switch (control->sar) {
59107e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
591184084a31SMat Martineau 		if (chan->sdu)
591284084a31SMat Martineau 			break;
59130a708f8fSGustavo F. Padovan 
591480b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
591584084a31SMat Martineau 		break;
59160a708f8fSGustavo F. Padovan 
59177e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
591884084a31SMat Martineau 		if (chan->sdu)
591984084a31SMat Martineau 			break;
59200a708f8fSGustavo F. Padovan 
5921dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
5922dbb50887SDaniel Borkmann 			break;
5923dbb50887SDaniel Borkmann 
59246f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
592503a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
59260a708f8fSGustavo F. Padovan 
592784084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
592884084a31SMat Martineau 			err = -EMSGSIZE;
592984084a31SMat Martineau 			break;
593084084a31SMat Martineau 		}
59310a708f8fSGustavo F. Padovan 
593284084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
593384084a31SMat Martineau 			break;
593484084a31SMat Martineau 
593584084a31SMat Martineau 		chan->sdu = skb;
593684084a31SMat Martineau 		chan->sdu_last_frag = skb;
593784084a31SMat Martineau 
593884084a31SMat Martineau 		skb = NULL;
593984084a31SMat Martineau 		err = 0;
59400a708f8fSGustavo F. Padovan 		break;
59410a708f8fSGustavo F. Padovan 
59427e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
59436f61fd47SGustavo F. Padovan 		if (!chan->sdu)
594484084a31SMat Martineau 			break;
59450a708f8fSGustavo F. Padovan 
594684084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
594784084a31SMat Martineau 				&chan->sdu_last_frag);
594884084a31SMat Martineau 		skb = NULL;
59490a708f8fSGustavo F. Padovan 
595084084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
595184084a31SMat Martineau 			break;
59520a708f8fSGustavo F. Padovan 
595384084a31SMat Martineau 		err = 0;
59540a708f8fSGustavo F. Padovan 		break;
59550a708f8fSGustavo F. Padovan 
59567e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
59576f61fd47SGustavo F. Padovan 		if (!chan->sdu)
595884084a31SMat Martineau 			break;
59590a708f8fSGustavo F. Padovan 
596084084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
596184084a31SMat Martineau 				&chan->sdu_last_frag);
596284084a31SMat Martineau 		skb = NULL;
59630a708f8fSGustavo F. Padovan 
596484084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
596584084a31SMat Martineau 			break;
59660a708f8fSGustavo F. Padovan 
596780b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
59680a708f8fSGustavo F. Padovan 
596984084a31SMat Martineau 		if (!err) {
597084084a31SMat Martineau 			/* Reassembly complete */
597184084a31SMat Martineau 			chan->sdu = NULL;
597284084a31SMat Martineau 			chan->sdu_last_frag = NULL;
597384084a31SMat Martineau 			chan->sdu_len = 0;
59740a708f8fSGustavo F. Padovan 		}
59750a708f8fSGustavo F. Padovan 		break;
59760a708f8fSGustavo F. Padovan 	}
59770a708f8fSGustavo F. Padovan 
597884084a31SMat Martineau 	if (err) {
59790a708f8fSGustavo F. Padovan 		kfree_skb(skb);
59806f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
59816f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
598284084a31SMat Martineau 		chan->sdu_last_frag = NULL;
598384084a31SMat Martineau 		chan->sdu_len = 0;
598484084a31SMat Martineau 	}
59850a708f8fSGustavo F. Padovan 
598684084a31SMat Martineau 	return err;
59870a708f8fSGustavo F. Padovan }
59880a708f8fSGustavo F. Padovan 
598932b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
599032b32735SMat Martineau {
599132b32735SMat Martineau 	/* Placeholder */
599232b32735SMat Martineau 	return 0;
599332b32735SMat Martineau }
599432b32735SMat Martineau 
5995e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
59960a708f8fSGustavo F. Padovan {
599761aa4f5bSMat Martineau 	u8 event;
599861aa4f5bSMat Martineau 
599961aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
600061aa4f5bSMat Martineau 		return;
600161aa4f5bSMat Martineau 
600261aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6003401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
60040a708f8fSGustavo F. Padovan }
60050a708f8fSGustavo F. Padovan 
6006d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6007d2a7ac5dSMat Martineau {
600863838725SMat Martineau 	int err = 0;
600963838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
601063838725SMat Martineau 	 * until a gap is encountered.
601163838725SMat Martineau 	 */
601263838725SMat Martineau 
601363838725SMat Martineau 	BT_DBG("chan %p", chan);
601463838725SMat Martineau 
601563838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
601663838725SMat Martineau 		struct sk_buff *skb;
601763838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
601863838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
601963838725SMat Martineau 
602063838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
602163838725SMat Martineau 
602263838725SMat Martineau 		if (!skb)
602363838725SMat Martineau 			break;
602463838725SMat Martineau 
602563838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
602663838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
6027a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
602863838725SMat Martineau 		if (err)
602963838725SMat Martineau 			break;
603063838725SMat Martineau 	}
603163838725SMat Martineau 
603263838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
603363838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
603463838725SMat Martineau 		l2cap_send_ack(chan);
603563838725SMat Martineau 	}
603663838725SMat Martineau 
603763838725SMat Martineau 	return err;
6038d2a7ac5dSMat Martineau }
6039d2a7ac5dSMat Martineau 
6040d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6041d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6042d2a7ac5dSMat Martineau {
6043f80842a8SMat Martineau 	struct sk_buff *skb;
6044f80842a8SMat Martineau 
6045f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6046f80842a8SMat Martineau 
6047f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6048f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
60495e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6050f80842a8SMat Martineau 		return;
6051f80842a8SMat Martineau 	}
6052f80842a8SMat Martineau 
6053f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6054f80842a8SMat Martineau 
6055f80842a8SMat Martineau 	if (skb == NULL) {
6056f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6057f80842a8SMat Martineau 		       control->reqseq);
6058f80842a8SMat Martineau 		return;
6059f80842a8SMat Martineau 	}
6060f80842a8SMat Martineau 
6061a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6062f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
60635e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6064f80842a8SMat Martineau 		return;
6065f80842a8SMat Martineau 	}
6066f80842a8SMat Martineau 
6067f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6068f80842a8SMat Martineau 
6069f80842a8SMat Martineau 	if (control->poll) {
6070f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6071f80842a8SMat Martineau 
6072f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6073f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6074f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6075f80842a8SMat Martineau 
6076f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6077f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6078f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6079f80842a8SMat Martineau 		}
6080f80842a8SMat Martineau 	} else {
6081f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6082f80842a8SMat Martineau 
6083f80842a8SMat Martineau 		if (control->final) {
6084f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6085f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6086f80842a8SMat Martineau 						&chan->conn_state))
6087f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6088f80842a8SMat Martineau 		} else {
6089f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6090f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6091f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6092f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6093f80842a8SMat Martineau 			}
6094f80842a8SMat Martineau 		}
6095f80842a8SMat Martineau 	}
6096d2a7ac5dSMat Martineau }
6097d2a7ac5dSMat Martineau 
6098d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6099d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6100d2a7ac5dSMat Martineau {
6101fcd289dfSMat Martineau 	struct sk_buff *skb;
6102fcd289dfSMat Martineau 
6103fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6104fcd289dfSMat Martineau 
6105fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6106fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61075e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6108fcd289dfSMat Martineau 		return;
6109fcd289dfSMat Martineau 	}
6110fcd289dfSMat Martineau 
6111fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6112fcd289dfSMat Martineau 
6113fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6114a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6115fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61165e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6117fcd289dfSMat Martineau 		return;
6118fcd289dfSMat Martineau 	}
6119fcd289dfSMat Martineau 
6120fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6121fcd289dfSMat Martineau 
6122fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6123fcd289dfSMat Martineau 
6124fcd289dfSMat Martineau 	if (control->final) {
6125fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6126fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6127fcd289dfSMat Martineau 	} else {
6128fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6129fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6130fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6131fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6132fcd289dfSMat Martineau 	}
6133d2a7ac5dSMat Martineau }
6134d2a7ac5dSMat Martineau 
61354b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
61364b51dae9SMat Martineau {
61374b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
61384b51dae9SMat Martineau 
61394b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
61404b51dae9SMat Martineau 	       chan->expected_tx_seq);
61414b51dae9SMat Martineau 
61424b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
61434b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61444b51dae9SMat Martineau 		    chan->tx_win) {
61454b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
61464b51dae9SMat Martineau 			 * invalid packets.
61474b51dae9SMat Martineau 			 */
61484b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
61494b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
61504b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
61514b51dae9SMat Martineau 			} else {
61524b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
61534b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
61544b51dae9SMat Martineau 			}
61554b51dae9SMat Martineau 		}
61564b51dae9SMat Martineau 
61574b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
61584b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
61594b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
61604b51dae9SMat Martineau 		}
61614b51dae9SMat Martineau 
61624b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
61634b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
61644b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
61654b51dae9SMat Martineau 		}
61664b51dae9SMat Martineau 
61674b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
61684b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
61694b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
61704b51dae9SMat Martineau 		}
61714b51dae9SMat Martineau 	}
61724b51dae9SMat Martineau 
61734b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
61744b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61754b51dae9SMat Martineau 		    chan->tx_win) {
61764b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
61774b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
61784b51dae9SMat Martineau 		} else {
61794b51dae9SMat Martineau 			BT_DBG("Expected");
61804b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
61814b51dae9SMat Martineau 		}
61824b51dae9SMat Martineau 	}
61834b51dae9SMat Martineau 
61844b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
61852d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
61864b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
61874b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
61884b51dae9SMat Martineau 	}
61894b51dae9SMat Martineau 
61904b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
61914b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
61924b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
61934b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
61944b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
61954b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
61964b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
61974b51dae9SMat Martineau 		 * request.
61984b51dae9SMat Martineau 		 *
61994b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
62004b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
62014b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
62024b51dae9SMat Martineau 		 *
62034b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
62044b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
62054b51dae9SMat Martineau 		 * causes a disconnect.
62064b51dae9SMat Martineau 		 */
62074b51dae9SMat Martineau 
62084b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62094b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
62104b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
62114b51dae9SMat Martineau 		} else {
62124b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62134b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62144b51dae9SMat Martineau 		}
62154b51dae9SMat Martineau 	} else {
62164b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
62174b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
62184b51dae9SMat Martineau 	}
62194b51dae9SMat Martineau }
62204b51dae9SMat Martineau 
6221d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6222d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6223d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6224d2a7ac5dSMat Martineau {
6225d2a7ac5dSMat Martineau 	int err = 0;
6226941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6227d2a7ac5dSMat Martineau 
6228d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6229d2a7ac5dSMat Martineau 	       event);
6230d2a7ac5dSMat Martineau 
6231d2a7ac5dSMat Martineau 	switch (event) {
6232d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6233d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6234d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6235d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6236d2a7ac5dSMat Martineau 
6237d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6238d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6239d2a7ac5dSMat Martineau 				       control->txseq);
6240d2a7ac5dSMat Martineau 				break;
6241d2a7ac5dSMat Martineau 			}
6242d2a7ac5dSMat Martineau 
6243d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6244d2a7ac5dSMat Martineau 							   control->txseq);
6245d2a7ac5dSMat Martineau 
6246d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6247941247f9SPeter Senna Tschudin 			skb_in_use = true;
6248d2a7ac5dSMat Martineau 
6249d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6250d2a7ac5dSMat Martineau 			if (err)
6251d2a7ac5dSMat Martineau 				break;
6252d2a7ac5dSMat Martineau 
6253d2a7ac5dSMat Martineau 			if (control->final) {
6254d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6255d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6256d2a7ac5dSMat Martineau 					control->final = 0;
6257d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6258d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6259d2a7ac5dSMat Martineau 				}
6260d2a7ac5dSMat Martineau 			}
6261d2a7ac5dSMat Martineau 
6262d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6263d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6264d2a7ac5dSMat Martineau 			break;
6265d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6266d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6267d2a7ac5dSMat Martineau 
6268d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6269d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6270d2a7ac5dSMat Martineau 			 * when local busy is exited.
6271d2a7ac5dSMat Martineau 			 */
6272d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6273d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6274d2a7ac5dSMat Martineau 				       control->txseq);
6275d2a7ac5dSMat Martineau 				break;
6276d2a7ac5dSMat Martineau 			}
6277d2a7ac5dSMat Martineau 
6278d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6279d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6280d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6281d2a7ac5dSMat Martineau 			 */
6282d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6283941247f9SPeter Senna Tschudin 			skb_in_use = true;
6284d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6285d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6286d2a7ac5dSMat Martineau 
6287d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6288d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6289d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6290d2a7ac5dSMat Martineau 
6291d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6292d2a7ac5dSMat Martineau 			break;
6293d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6294d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6295d2a7ac5dSMat Martineau 			break;
6296d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6297d2a7ac5dSMat Martineau 			break;
6298d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6299d2a7ac5dSMat Martineau 		default:
63005e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6301d2a7ac5dSMat Martineau 			break;
6302d2a7ac5dSMat Martineau 		}
6303d2a7ac5dSMat Martineau 		break;
6304d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6305d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6306d2a7ac5dSMat Martineau 		if (control->final) {
6307d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6308d2a7ac5dSMat Martineau 
6309e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6310e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6311d2a7ac5dSMat Martineau 				control->final = 0;
6312d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6313d2a7ac5dSMat Martineau 			}
6314d2a7ac5dSMat Martineau 
6315d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6316d2a7ac5dSMat Martineau 		} else if (control->poll) {
6317d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6318d2a7ac5dSMat Martineau 		} else {
6319d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6320d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6321d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6322d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6323d2a7ac5dSMat Martineau 
6324d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6325d2a7ac5dSMat Martineau 		}
6326d2a7ac5dSMat Martineau 		break;
6327d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6328d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6329d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6330d2a7ac5dSMat Martineau 		if (control && control->poll) {
6331d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6332d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6333d2a7ac5dSMat Martineau 		}
6334d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6335d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6336d2a7ac5dSMat Martineau 		break;
6337d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6338d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6339d2a7ac5dSMat Martineau 		break;
6340d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6341d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6342d2a7ac5dSMat Martineau 		break;
6343d2a7ac5dSMat Martineau 	default:
6344d2a7ac5dSMat Martineau 		break;
6345d2a7ac5dSMat Martineau 	}
6346d2a7ac5dSMat Martineau 
6347d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6348d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6349d2a7ac5dSMat Martineau 		kfree_skb(skb);
6350d2a7ac5dSMat Martineau 	}
6351d2a7ac5dSMat Martineau 
6352d2a7ac5dSMat Martineau 	return err;
6353d2a7ac5dSMat Martineau }
6354d2a7ac5dSMat Martineau 
6355d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6356d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6357d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6358d2a7ac5dSMat Martineau {
6359d2a7ac5dSMat Martineau 	int err = 0;
6360d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6361941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6362d2a7ac5dSMat Martineau 
6363d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6364d2a7ac5dSMat Martineau 	       event);
6365d2a7ac5dSMat Martineau 
6366d2a7ac5dSMat Martineau 	switch (event) {
6367d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6368d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6369d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6370d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6371d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6372d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6373941247f9SPeter Senna Tschudin 			skb_in_use = true;
6374d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6375d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6376d2a7ac5dSMat Martineau 
6377d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6378d2a7ac5dSMat Martineau 			break;
6379d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6380d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6381d2a7ac5dSMat Martineau 
6382d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6383d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6384941247f9SPeter Senna Tschudin 			skb_in_use = true;
6385d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6386d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6387d2a7ac5dSMat Martineau 
6388d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6389d2a7ac5dSMat Martineau 			if (err)
6390d2a7ac5dSMat Martineau 				break;
6391d2a7ac5dSMat Martineau 
6392d2a7ac5dSMat Martineau 			break;
6393d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6394d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6395d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6396d2a7ac5dSMat Martineau 			 * the missing frames.
6397d2a7ac5dSMat Martineau 			 */
6398d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6399941247f9SPeter Senna Tschudin 			skb_in_use = true;
6400d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6401d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6402d2a7ac5dSMat Martineau 
6403d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6404d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6405d2a7ac5dSMat Martineau 			break;
6406d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6407d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6408d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6409d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6410d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6411d2a7ac5dSMat Martineau 			 */
6412d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6413941247f9SPeter Senna Tschudin 			skb_in_use = true;
6414d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6415d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6416d2a7ac5dSMat Martineau 
6417d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6418d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6419d2a7ac5dSMat Martineau 			break;
6420d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6421d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6422d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6423d2a7ac5dSMat Martineau 			break;
6424d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6425d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6426d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6427d2a7ac5dSMat Martineau 			 */
6428d2a7ac5dSMat Martineau 			break;
6429d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6430d2a7ac5dSMat Martineau 			break;
6431d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6432d2a7ac5dSMat Martineau 		default:
64335e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6434d2a7ac5dSMat Martineau 			break;
6435d2a7ac5dSMat Martineau 		}
6436d2a7ac5dSMat Martineau 		break;
6437d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6438d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6439d2a7ac5dSMat Martineau 		if (control->final) {
6440d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6441d2a7ac5dSMat Martineau 
6442d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6443d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6444d2a7ac5dSMat Martineau 				control->final = 0;
6445d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6446d2a7ac5dSMat Martineau 			}
6447d2a7ac5dSMat Martineau 
6448d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6449d2a7ac5dSMat Martineau 		} else if (control->poll) {
6450d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6451d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6452d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6453d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6454d2a7ac5dSMat Martineau 			}
6455d2a7ac5dSMat Martineau 
6456d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6457d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6458d2a7ac5dSMat Martineau 		} else {
6459d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6460d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6461d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6462d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6463d2a7ac5dSMat Martineau 
6464d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6465d2a7ac5dSMat Martineau 		}
6466d2a7ac5dSMat Martineau 		break;
6467d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6468d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6469d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6470d2a7ac5dSMat Martineau 		if (control->poll) {
6471d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6472d2a7ac5dSMat Martineau 		} else {
6473d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6474d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6475d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6476d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6477d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6478d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6479d2a7ac5dSMat Martineau 		}
6480d2a7ac5dSMat Martineau 
6481d2a7ac5dSMat Martineau 		break;
6482d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6483d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6484d2a7ac5dSMat Martineau 		break;
6485d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6486d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6487d2a7ac5dSMat Martineau 		break;
6488d2a7ac5dSMat Martineau 	}
6489d2a7ac5dSMat Martineau 
6490d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6491d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6492d2a7ac5dSMat Martineau 		kfree_skb(skb);
6493d2a7ac5dSMat Martineau 	}
6494d2a7ac5dSMat Martineau 
6495d2a7ac5dSMat Martineau 	return err;
6496d2a7ac5dSMat Martineau }
6497d2a7ac5dSMat Martineau 
649832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
649932b32735SMat Martineau {
650032b32735SMat Martineau 	BT_DBG("chan %p", chan);
650132b32735SMat Martineau 
650232b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
650332b32735SMat Martineau 
650432b32735SMat Martineau 	if (chan->hs_hcon)
650532b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
650632b32735SMat Martineau 	else
650732b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
650832b32735SMat Martineau 
650932b32735SMat Martineau 	return l2cap_resegment(chan);
651032b32735SMat Martineau }
651132b32735SMat Martineau 
651232b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
651332b32735SMat Martineau 				 struct l2cap_ctrl *control,
651432b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
651532b32735SMat Martineau {
651632b32735SMat Martineau 	int err;
651732b32735SMat Martineau 
651832b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
651932b32735SMat Martineau 	       event);
652032b32735SMat Martineau 
652132b32735SMat Martineau 	if (!control->poll)
652232b32735SMat Martineau 		return -EPROTO;
652332b32735SMat Martineau 
652432b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
652532b32735SMat Martineau 
652632b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
652732b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
652832b32735SMat Martineau 	else
652932b32735SMat Martineau 		chan->tx_send_head = NULL;
653032b32735SMat Martineau 
653132b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
653232b32735SMat Martineau 	 * by the receiver.
653332b32735SMat Martineau 	 */
653432b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
653532b32735SMat Martineau 	chan->unacked_frames = 0;
653632b32735SMat Martineau 
653732b32735SMat Martineau 	err = l2cap_finish_move(chan);
653832b32735SMat Martineau 	if (err)
653932b32735SMat Martineau 		return err;
654032b32735SMat Martineau 
654132b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
654232b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
654332b32735SMat Martineau 
654432b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
654532b32735SMat Martineau 		return -EPROTO;
654632b32735SMat Martineau 
654732b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
654832b32735SMat Martineau }
654932b32735SMat Martineau 
655032b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
655132b32735SMat Martineau 				 struct l2cap_ctrl *control,
655232b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
655332b32735SMat Martineau {
655432b32735SMat Martineau 	int err;
655532b32735SMat Martineau 
655632b32735SMat Martineau 	if (!control->final)
655732b32735SMat Martineau 		return -EPROTO;
655832b32735SMat Martineau 
655932b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
656032b32735SMat Martineau 
656132b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
656232b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
656332b32735SMat Martineau 
656432b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
656532b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
656632b32735SMat Martineau 	else
656732b32735SMat Martineau 		chan->tx_send_head = NULL;
656832b32735SMat Martineau 
656932b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
657032b32735SMat Martineau 	 * by the receiver.
657132b32735SMat Martineau 	 */
657232b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
657332b32735SMat Martineau 	chan->unacked_frames = 0;
657432b32735SMat Martineau 
657532b32735SMat Martineau 	if (chan->hs_hcon)
657632b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
657732b32735SMat Martineau 	else
657832b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
657932b32735SMat Martineau 
658032b32735SMat Martineau 	err = l2cap_resegment(chan);
658132b32735SMat Martineau 
658232b32735SMat Martineau 	if (!err)
658332b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
658432b32735SMat Martineau 
658532b32735SMat Martineau 	return err;
658632b32735SMat Martineau }
658732b32735SMat Martineau 
6588d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6589d2a7ac5dSMat Martineau {
6590d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6591d2a7ac5dSMat Martineau 	u16 unacked;
6592d2a7ac5dSMat Martineau 
6593d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6594d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6595d2a7ac5dSMat Martineau }
6596d2a7ac5dSMat Martineau 
6597cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6598cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
65990a708f8fSGustavo F. Padovan {
6600d2a7ac5dSMat Martineau 	int err = 0;
6601d2a7ac5dSMat Martineau 
6602d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6603d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6604d2a7ac5dSMat Martineau 
6605d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6606d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6607d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6608d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6609d2a7ac5dSMat Martineau 			break;
6610d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6611d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6612d2a7ac5dSMat Martineau 						       event);
6613d2a7ac5dSMat Martineau 			break;
661432b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
661532b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
661632b32735SMat Martineau 			break;
661732b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
661832b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
661932b32735SMat Martineau 			break;
6620d2a7ac5dSMat Martineau 		default:
6621d2a7ac5dSMat Martineau 			/* shut it down */
6622d2a7ac5dSMat Martineau 			break;
6623d2a7ac5dSMat Martineau 		}
6624d2a7ac5dSMat Martineau 	} else {
6625d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6626d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6627d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
66285e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6629d2a7ac5dSMat Martineau 	}
6630d2a7ac5dSMat Martineau 
6631d2a7ac5dSMat Martineau 	return err;
6632cec8ab6eSMat Martineau }
6633cec8ab6eSMat Martineau 
6634cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6635cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6636cec8ab6eSMat Martineau {
66374b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
66384b51dae9SMat Martineau 	       chan->rx_state);
66394b51dae9SMat Martineau 
66404b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
66414b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
66424b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
66434b51dae9SMat Martineau 
66444b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
66454b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
66464b51dae9SMat Martineau 
66474b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
66484b51dae9SMat Martineau 
66494b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
66504b51dae9SMat Martineau 	} else {
66514b51dae9SMat Martineau 		if (chan->sdu) {
66524b51dae9SMat Martineau 			kfree_skb(chan->sdu);
66534b51dae9SMat Martineau 			chan->sdu = NULL;
66544b51dae9SMat Martineau 		}
66554b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
66564b51dae9SMat Martineau 		chan->sdu_len = 0;
66574b51dae9SMat Martineau 
66584b51dae9SMat Martineau 		if (skb) {
66594b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
66604b51dae9SMat Martineau 			kfree_skb(skb);
66614b51dae9SMat Martineau 		}
66624b51dae9SMat Martineau 	}
66634b51dae9SMat Martineau 
66644b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
66654b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
66664b51dae9SMat Martineau 
66679a544210SPrasanna Karthik 	return 0;
6668cec8ab6eSMat Martineau }
6669cec8ab6eSMat Martineau 
6670cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6671cec8ab6eSMat Martineau {
6672a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
6673cec8ab6eSMat Martineau 	u16 len;
6674cec8ab6eSMat Martineau 	u8 event;
66750a708f8fSGustavo F. Padovan 
6676b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6677b76bbd66SMat Martineau 
66780a708f8fSGustavo F. Padovan 	len = skb->len;
66790a708f8fSGustavo F. Padovan 
66800a708f8fSGustavo F. Padovan 	/*
66810a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
66820a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6683cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
66840a708f8fSGustavo F. Padovan 	 */
668547d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
66860a708f8fSGustavo F. Padovan 		goto drop;
66870a708f8fSGustavo F. Padovan 
6688cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
668903a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
66900a708f8fSGustavo F. Padovan 
669147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
669203a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
66930a708f8fSGustavo F. Padovan 
669447d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
66955e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
66960a708f8fSGustavo F. Padovan 		goto drop;
66970a708f8fSGustavo F. Padovan 	}
66980a708f8fSGustavo F. Padovan 
6699dbb50887SDaniel Borkmann 	if ((chan->mode == L2CAP_MODE_ERTM ||
6700dbb50887SDaniel Borkmann 	     chan->mode == L2CAP_MODE_STREAMING) && sk_filter(chan->data, skb))
6701dbb50887SDaniel Borkmann 		goto drop;
6702dbb50887SDaniel Borkmann 
6703cec8ab6eSMat Martineau 	if (!control->sframe) {
6704cec8ab6eSMat Martineau 		int err;
67050a708f8fSGustavo F. Padovan 
6706cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6707cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6708cec8ab6eSMat Martineau 		       control->txseq);
6709836be934SAndrei Emeltchenko 
6710cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6711cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6712cec8ab6eSMat Martineau 		 */
6713cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
67140a708f8fSGustavo F. Padovan 			goto drop;
67150a708f8fSGustavo F. Padovan 
6716cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6717cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6718cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
67190a708f8fSGustavo F. Padovan 		} else {
6720cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6721cec8ab6eSMat Martineau 		}
6722cec8ab6eSMat Martineau 
6723cec8ab6eSMat Martineau 		if (err)
67245e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6725cec8ab6eSMat Martineau 	} else {
6726cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6727cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6728cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6729cec8ab6eSMat Martineau 		};
6730cec8ab6eSMat Martineau 
6731cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6732cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6733cec8ab6eSMat Martineau 			goto drop;
6734cec8ab6eSMat Martineau 
6735cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6736cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6737cec8ab6eSMat Martineau 		       control->super);
6738cec8ab6eSMat Martineau 
67390a708f8fSGustavo F. Padovan 		if (len != 0) {
67401bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
67415e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67420a708f8fSGustavo F. Padovan 			goto drop;
67430a708f8fSGustavo F. Padovan 		}
67440a708f8fSGustavo F. Padovan 
6745cec8ab6eSMat Martineau 		/* Validate F and P bits */
6746cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6747cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6748cec8ab6eSMat Martineau 			goto drop;
6749cec8ab6eSMat Martineau 
6750cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6751cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
67525e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67530a708f8fSGustavo F. Padovan 	}
67540a708f8fSGustavo F. Padovan 
67550a708f8fSGustavo F. Padovan 	return 0;
67560a708f8fSGustavo F. Padovan 
67570a708f8fSGustavo F. Padovan drop:
67580a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67590a708f8fSGustavo F. Padovan 	return 0;
67600a708f8fSGustavo F. Padovan }
67610a708f8fSGustavo F. Padovan 
6762b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6763b1c325c2SJohan Hedberg {
6764b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6765b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6766b1c325c2SJohan Hedberg 	u16 return_credits;
6767b1c325c2SJohan Hedberg 
676896cd8eaaSLuiz Augusto von Dentz 	return_credits = ((chan->imtu / chan->mps) + 1) - chan->rx_credits;
6769b1c325c2SJohan Hedberg 
677096cd8eaaSLuiz Augusto von Dentz 	if (!return_credits)
677196cd8eaaSLuiz Augusto von Dentz 		return;
6772b1c325c2SJohan Hedberg 
6773b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6774b1c325c2SJohan Hedberg 
6775b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6776b1c325c2SJohan Hedberg 
6777b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6778b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6779b1c325c2SJohan Hedberg 
6780b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6781b1c325c2SJohan Hedberg 
6782b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6783b1c325c2SJohan Hedberg }
6784b1c325c2SJohan Hedberg 
678596cd8eaaSLuiz Augusto von Dentz static int l2cap_le_recv(struct l2cap_chan *chan, struct sk_buff *skb)
678696cd8eaaSLuiz Augusto von Dentz {
678796cd8eaaSLuiz Augusto von Dentz 	int err;
678896cd8eaaSLuiz Augusto von Dentz 
678996cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
679096cd8eaaSLuiz Augusto von Dentz 
679196cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
679296cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
679396cd8eaaSLuiz Augusto von Dentz 
679496cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
679596cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
679696cd8eaaSLuiz Augusto von Dentz 
679796cd8eaaSLuiz Augusto von Dentz 	return err;
679896cd8eaaSLuiz Augusto von Dentz }
679996cd8eaaSLuiz Augusto von Dentz 
6800fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6801fad5fc89SJohan Hedberg {
6802aac23bf6SJohan Hedberg 	int err;
6803fad5fc89SJohan Hedberg 
6804aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6805aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6806dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
6807fad5fc89SJohan Hedberg 		return -ENOBUFS;
6808aac23bf6SJohan Hedberg 	}
6809aac23bf6SJohan Hedberg 
6810aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6811aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6812aac23bf6SJohan Hedberg 		return -ENOBUFS;
6813aac23bf6SJohan Hedberg 	}
6814fad5fc89SJohan Hedberg 
6815fad5fc89SJohan Hedberg 	chan->rx_credits--;
6816fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6817fad5fc89SJohan Hedberg 
681896cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
681996cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
682096cd8eaaSLuiz Augusto von Dentz 	 */
682196cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
6822fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
6823fad5fc89SJohan Hedberg 
6824aac23bf6SJohan Hedberg 	err = 0;
6825aac23bf6SJohan Hedberg 
6826aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6827aac23bf6SJohan Hedberg 		u16 sdu_len;
6828aac23bf6SJohan Hedberg 
6829aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6830aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6831aac23bf6SJohan Hedberg 
6832aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6833aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6834aac23bf6SJohan Hedberg 
6835aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6836aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6837aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6838aac23bf6SJohan Hedberg 			goto failed;
6839aac23bf6SJohan Hedberg 		}
6840aac23bf6SJohan Hedberg 
6841aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6842aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6843aac23bf6SJohan Hedberg 			err = -EINVAL;
6844aac23bf6SJohan Hedberg 			goto failed;
6845aac23bf6SJohan Hedberg 		}
6846aac23bf6SJohan Hedberg 
6847aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
684896cd8eaaSLuiz Augusto von Dentz 			return l2cap_le_recv(chan, skb);
6849aac23bf6SJohan Hedberg 
6850aac23bf6SJohan Hedberg 		chan->sdu = skb;
6851aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6852aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6853aac23bf6SJohan Hedberg 
6854a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
6855a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
6856a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
6857a5c3021bSLuiz Augusto von Dentz 
6858a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
6859a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
6860a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
6861a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
6862a5c3021bSLuiz Augusto von Dentz 		}
6863a5c3021bSLuiz Augusto von Dentz 
6864aac23bf6SJohan Hedberg 		return 0;
6865aac23bf6SJohan Hedberg 	}
6866aac23bf6SJohan Hedberg 
6867aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6868aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6869aac23bf6SJohan Hedberg 
6870aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6871aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6872aac23bf6SJohan Hedberg 		err = -EINVAL;
6873aac23bf6SJohan Hedberg 		goto failed;
6874aac23bf6SJohan Hedberg 	}
6875aac23bf6SJohan Hedberg 
6876aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6877aac23bf6SJohan Hedberg 	skb = NULL;
6878aac23bf6SJohan Hedberg 
6879aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
688096cd8eaaSLuiz Augusto von Dentz 		err = l2cap_le_recv(chan, chan->sdu);
6881aac23bf6SJohan Hedberg 		if (!err) {
6882aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6883aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6884aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6885aac23bf6SJohan Hedberg 		}
6886aac23bf6SJohan Hedberg 	}
6887aac23bf6SJohan Hedberg 
6888aac23bf6SJohan Hedberg failed:
6889aac23bf6SJohan Hedberg 	if (err) {
6890aac23bf6SJohan Hedberg 		kfree_skb(skb);
6891aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6892aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6893aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6894aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6895aac23bf6SJohan Hedberg 	}
6896aac23bf6SJohan Hedberg 
6897aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6898aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6899aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6900aac23bf6SJohan Hedberg 	 */
6901aac23bf6SJohan Hedberg 	return 0;
6902fad5fc89SJohan Hedberg }
6903fad5fc89SJohan Hedberg 
690413ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
690513ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
69060a708f8fSGustavo F. Padovan {
690748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
69080a708f8fSGustavo F. Padovan 
6909baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
691048454079SGustavo F. Padovan 	if (!chan) {
691197e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
691297e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
691397e8e89dSAndrei Emeltchenko 			if (!chan) {
691497e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
691513ca56e0SAndrei Emeltchenko 				return;
691697e8e89dSAndrei Emeltchenko 			}
691797e8e89dSAndrei Emeltchenko 
691897e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
691997e8e89dSAndrei Emeltchenko 		} else {
69200a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
69216be36555SAndrei Emeltchenko 			/* Drop packet and return */
69223379013bSDan Carpenter 			kfree_skb(skb);
692313ca56e0SAndrei Emeltchenko 			return;
69240a708f8fSGustavo F. Padovan 		}
692597e8e89dSAndrei Emeltchenko 	}
69260a708f8fSGustavo F. Padovan 
692749208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
69280a708f8fSGustavo F. Padovan 
6929315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
6930315917e0SJohan Hedberg 	 * procdure is done simply assume that the channel is supported
6931315917e0SJohan Hedberg 	 * and mark it as ready.
6932315917e0SJohan Hedberg 	 */
6933315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
6934315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
6935315917e0SJohan Hedberg 
693689bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
69370a708f8fSGustavo F. Padovan 		goto drop;
69380a708f8fSGustavo F. Padovan 
69390c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
694038319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
6941fad5fc89SJohan Hedberg 		if (l2cap_le_data_rcv(chan, skb) < 0)
6942fad5fc89SJohan Hedberg 			goto drop;
6943fad5fc89SJohan Hedberg 
6944fad5fc89SJohan Hedberg 		goto done;
6945fad5fc89SJohan Hedberg 
69460a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
69470a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
69480a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
69490a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
69500a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
69510a708f8fSGustavo F. Padovan 
69522c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
69532c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
69540a708f8fSGustavo F. Padovan 			goto drop;
69552c96e03dSSzymon Janc 		}
69560a708f8fSGustavo F. Padovan 
695780b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
69580a708f8fSGustavo F. Padovan 			goto done;
69590a708f8fSGustavo F. Padovan 		break;
69600a708f8fSGustavo F. Padovan 
69610a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
69620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6963cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
69640a708f8fSGustavo F. Padovan 		goto done;
69650a708f8fSGustavo F. Padovan 
69660a708f8fSGustavo F. Padovan 	default:
69670c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
69680a708f8fSGustavo F. Padovan 		break;
69690a708f8fSGustavo F. Padovan 	}
69700a708f8fSGustavo F. Padovan 
69710a708f8fSGustavo F. Padovan drop:
69720a708f8fSGustavo F. Padovan 	kfree_skb(skb);
69730a708f8fSGustavo F. Padovan 
69740a708f8fSGustavo F. Padovan done:
69756be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
69760a708f8fSGustavo F. Padovan }
69770a708f8fSGustavo F. Padovan 
697884104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
697984104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
69800a708f8fSGustavo F. Padovan {
6981ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
698223691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
69830a708f8fSGustavo F. Padovan 
6984ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
6985a24cce14SJohan Hedberg 		goto free_skb;
6986ae4fd2d3SMarcel Holtmann 
6987bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6988bf20fd4eSJohan Hedberg 					ACL_LINK);
698923691d75SGustavo F. Padovan 	if (!chan)
6990a24cce14SJohan Hedberg 		goto free_skb;
69910a708f8fSGustavo F. Padovan 
69925b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
69930a708f8fSGustavo F. Padovan 
699489bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
69950a708f8fSGustavo F. Padovan 		goto drop;
69960a708f8fSGustavo F. Padovan 
6997e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
69980a708f8fSGustavo F. Padovan 		goto drop;
69990a708f8fSGustavo F. Padovan 
70002edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
7001a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
7002a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
70032edf870dSMarcel Holtmann 
7004a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
7005a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
700684104b24SAndrei Emeltchenko 		return;
7007a24cce14SJohan Hedberg 	}
70080a708f8fSGustavo F. Padovan 
70090a708f8fSGustavo F. Padovan drop:
7010a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
7011a24cce14SJohan Hedberg free_skb:
70120a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70130a708f8fSGustavo F. Padovan }
70140a708f8fSGustavo F. Padovan 
70150a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
70160a708f8fSGustavo F. Padovan {
70170a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
701861a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
70190a708f8fSGustavo F. Padovan 	u16 cid, len;
70200a708f8fSGustavo F. Padovan 	__le16 psm;
70210a708f8fSGustavo F. Padovan 
702261a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
702361a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
702461a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
702561a939c6SJohan Hedberg 		return;
702661a939c6SJohan Hedberg 	}
702761a939c6SJohan Hedberg 
70280a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
70290a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
70300a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
70310a708f8fSGustavo F. Padovan 
70320a708f8fSGustavo F. Padovan 	if (len != skb->len) {
70330a708f8fSGustavo F. Padovan 		kfree_skb(skb);
70340a708f8fSGustavo F. Padovan 		return;
70350a708f8fSGustavo F. Padovan 	}
70360a708f8fSGustavo F. Padovan 
70379e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
70389e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
70399e1d7e15SJohan Hedberg 	 */
70409e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
7041dcc36c16SJohan Hedberg 	    hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
7042a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
7043e493150eSJohan Hedberg 		kfree_skb(skb);
7044e493150eSJohan Hedberg 		return;
7045e493150eSJohan Hedberg 	}
7046e493150eSJohan Hedberg 
70470a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
70480a708f8fSGustavo F. Padovan 
70490a708f8fSGustavo F. Padovan 	switch (cid) {
70500a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
70510a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
70520a708f8fSGustavo F. Padovan 		break;
70530a708f8fSGustavo F. Padovan 
70540a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7055097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
70560181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
70570a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
70580a708f8fSGustavo F. Padovan 		break;
70590a708f8fSGustavo F. Padovan 
7060a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7061a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7062a2877629SMarcel Holtmann 		break;
7063a2877629SMarcel Holtmann 
70640a708f8fSGustavo F. Padovan 	default:
70650a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
70660a708f8fSGustavo F. Padovan 		break;
70670a708f8fSGustavo F. Padovan 	}
70680a708f8fSGustavo F. Padovan }
70690a708f8fSGustavo F. Padovan 
707061a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
707161a939c6SJohan Hedberg {
707261a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
707361a939c6SJohan Hedberg 					       pending_rx_work);
707461a939c6SJohan Hedberg 	struct sk_buff *skb;
707561a939c6SJohan Hedberg 
707661a939c6SJohan Hedberg 	BT_DBG("");
707761a939c6SJohan Hedberg 
707861a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
707961a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
708061a939c6SJohan Hedberg }
708161a939c6SJohan Hedberg 
7082162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
7083162b49e7SJohan Hedberg {
7084162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
7085162b49e7SJohan Hedberg 	struct hci_chan *hchan;
7086162b49e7SJohan Hedberg 
7087162b49e7SJohan Hedberg 	if (conn)
7088162b49e7SJohan Hedberg 		return conn;
7089162b49e7SJohan Hedberg 
7090162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
7091162b49e7SJohan Hedberg 	if (!hchan)
7092162b49e7SJohan Hedberg 		return NULL;
7093162b49e7SJohan Hedberg 
709427f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
7095162b49e7SJohan Hedberg 	if (!conn) {
7096162b49e7SJohan Hedberg 		hci_chan_del(hchan);
7097162b49e7SJohan Hedberg 		return NULL;
7098162b49e7SJohan Hedberg 	}
7099162b49e7SJohan Hedberg 
7100162b49e7SJohan Hedberg 	kref_init(&conn->ref);
7101162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
710251bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
7103162b49e7SJohan Hedberg 	conn->hchan = hchan;
7104162b49e7SJohan Hedberg 
7105162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
7106162b49e7SJohan Hedberg 
7107162b49e7SJohan Hedberg 	switch (hcon->type) {
7108162b49e7SJohan Hedberg 	case LE_LINK:
7109162b49e7SJohan Hedberg 		if (hcon->hdev->le_mtu) {
7110162b49e7SJohan Hedberg 			conn->mtu = hcon->hdev->le_mtu;
7111162b49e7SJohan Hedberg 			break;
7112162b49e7SJohan Hedberg 		}
7113162b49e7SJohan Hedberg 		/* fall through */
7114162b49e7SJohan Hedberg 	default:
7115162b49e7SJohan Hedberg 		conn->mtu = hcon->hdev->acl_mtu;
7116162b49e7SJohan Hedberg 		break;
7117162b49e7SJohan Hedberg 	}
7118162b49e7SJohan Hedberg 
7119162b49e7SJohan Hedberg 	conn->feat_mask = 0;
7120162b49e7SJohan Hedberg 
71210bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
71220bd49fc7SJohan Hedberg 
71230bd49fc7SJohan Hedberg 	if (hcon->type == ACL_LINK &&
7124d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
71250bd49fc7SJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_A2MP;
7126162b49e7SJohan Hedberg 
7127d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
7128f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
7129b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
7130b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
7131b5ae344dSJohan Hedberg 
71325a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
7133162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
7134162b49e7SJohan Hedberg 
7135162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
7136162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
7137162b49e7SJohan Hedberg 
7138162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
7139162b49e7SJohan Hedberg 
714061a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
714161a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
7142f3d82d0cSJohan Hedberg 	INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr);
714361a939c6SJohan Hedberg 
7144162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
7145162b49e7SJohan Hedberg 
7146162b49e7SJohan Hedberg 	return conn;
7147162b49e7SJohan Hedberg }
7148162b49e7SJohan Hedberg 
7149162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) {
7150162b49e7SJohan Hedberg 	if (!psm)
7151162b49e7SJohan Hedberg 		return false;
7152162b49e7SJohan Hedberg 
7153162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
7154162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
7155162b49e7SJohan Hedberg 
7156162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
7157162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
7158162b49e7SJohan Hedberg }
7159162b49e7SJohan Hedberg 
7160162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7161162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
7162162b49e7SJohan Hedberg {
7163162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
7164162b49e7SJohan Hedberg 	struct hci_conn *hcon;
7165162b49e7SJohan Hedberg 	struct hci_dev *hdev;
7166162b49e7SJohan Hedberg 	int err;
7167162b49e7SJohan Hedberg 
7168162b49e7SJohan Hedberg 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
7169162b49e7SJohan Hedberg 	       dst_type, __le16_to_cpu(psm));
7170162b49e7SJohan Hedberg 
717139385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
7172162b49e7SJohan Hedberg 	if (!hdev)
7173162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
7174162b49e7SJohan Hedberg 
7175162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
7176162b49e7SJohan Hedberg 
7177162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
7178162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
7179162b49e7SJohan Hedberg 		err = -EINVAL;
7180162b49e7SJohan Hedberg 		goto done;
7181162b49e7SJohan Hedberg 	}
7182162b49e7SJohan Hedberg 
718321626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
718421626e62SJohan Hedberg 		err = -EINVAL;
718521626e62SJohan Hedberg 		goto done;
718621626e62SJohan Hedberg 	}
718721626e62SJohan Hedberg 
718821626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
7189162b49e7SJohan Hedberg 		err = -EINVAL;
7190162b49e7SJohan Hedberg 		goto done;
7191162b49e7SJohan Hedberg 	}
7192162b49e7SJohan Hedberg 
7193162b49e7SJohan Hedberg 	switch (chan->mode) {
7194162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
7195162b49e7SJohan Hedberg 		break;
7196162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
7197162b49e7SJohan Hedberg 		break;
7198162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
7199162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
7200162b49e7SJohan Hedberg 		if (!disable_ertm)
7201162b49e7SJohan Hedberg 			break;
7202162b49e7SJohan Hedberg 		/* fall through */
7203162b49e7SJohan Hedberg 	default:
7204beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
7205162b49e7SJohan Hedberg 		goto done;
7206162b49e7SJohan Hedberg 	}
7207162b49e7SJohan Hedberg 
7208162b49e7SJohan Hedberg 	switch (chan->state) {
7209162b49e7SJohan Hedberg 	case BT_CONNECT:
7210162b49e7SJohan Hedberg 	case BT_CONNECT2:
7211162b49e7SJohan Hedberg 	case BT_CONFIG:
7212162b49e7SJohan Hedberg 		/* Already connecting */
7213162b49e7SJohan Hedberg 		err = 0;
7214162b49e7SJohan Hedberg 		goto done;
7215162b49e7SJohan Hedberg 
7216162b49e7SJohan Hedberg 	case BT_CONNECTED:
7217162b49e7SJohan Hedberg 		/* Already connected */
7218162b49e7SJohan Hedberg 		err = -EISCONN;
7219162b49e7SJohan Hedberg 		goto done;
7220162b49e7SJohan Hedberg 
7221162b49e7SJohan Hedberg 	case BT_OPEN:
7222162b49e7SJohan Hedberg 	case BT_BOUND:
7223162b49e7SJohan Hedberg 		/* Can connect */
7224162b49e7SJohan Hedberg 		break;
7225162b49e7SJohan Hedberg 
7226162b49e7SJohan Hedberg 	default:
7227162b49e7SJohan Hedberg 		err = -EBADFD;
7228162b49e7SJohan Hedberg 		goto done;
7229162b49e7SJohan Hedberg 	}
7230162b49e7SJohan Hedberg 
7231162b49e7SJohan Hedberg 	/* Set destination address and psm */
7232162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
7233162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
7234162b49e7SJohan Hedberg 
7235162b49e7SJohan Hedberg 	chan->psm = psm;
7236162b49e7SJohan Hedberg 	chan->dcid = cid;
7237162b49e7SJohan Hedberg 
72386f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
72396f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
72406f77d8c7SAndre Guedes 		 */
72416f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
72426f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
72436f77d8c7SAndre Guedes 		else
72446f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
72456f77d8c7SAndre Guedes 
7246d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
72470ad06aa6SJohan Hedberg 			hcon = hci_connect_le(hdev, dst, dst_type,
7248fa142220SJakub Pawlowski 					      chan->sec_level,
7249fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
7250082f2300SSzymon Janc 					      HCI_ROLE_SLAVE, NULL);
72510ad06aa6SJohan Hedberg 		else
72520ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
72530ad06aa6SJohan Hedberg 						   chan->sec_level,
72540ad06aa6SJohan Hedberg 						   HCI_LE_CONN_TIMEOUT);
72550ad06aa6SJohan Hedberg 
72566f77d8c7SAndre Guedes 	} else {
7257d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
725804a6c589SAndre Guedes 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
72596f77d8c7SAndre Guedes 	}
7260162b49e7SJohan Hedberg 
7261162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
7262162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
7263162b49e7SJohan Hedberg 		goto done;
7264162b49e7SJohan Hedberg 	}
7265162b49e7SJohan Hedberg 
7266162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7267162b49e7SJohan Hedberg 	if (!conn) {
7268162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7269162b49e7SJohan Hedberg 		err = -ENOMEM;
7270162b49e7SJohan Hedberg 		goto done;
7271162b49e7SJohan Hedberg 	}
7272162b49e7SJohan Hedberg 
727302e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
727402e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
727502e246aeSJohan Hedberg 
7276162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7277162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7278162b49e7SJohan Hedberg 		err = -EBUSY;
727902e246aeSJohan Hedberg 		goto chan_unlock;
7280162b49e7SJohan Hedberg 	}
7281162b49e7SJohan Hedberg 
7282162b49e7SJohan Hedberg 	/* Update source addr of the socket */
7283162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
7284a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
7285162b49e7SJohan Hedberg 
728602e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
7287162b49e7SJohan Hedberg 
7288162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
7289162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
7290162b49e7SJohan Hedberg 
7291162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
7292162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7293162b49e7SJohan Hedberg 
729461202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
729561202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
729661202e4dSJohan Hedberg 	 */
729761202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
729861202e4dSJohan Hedberg 	chan->sport = 0;
729961202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
730061202e4dSJohan Hedberg 
7301162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
7302162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7303162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
7304e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
7305162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
7306162b49e7SJohan Hedberg 		} else
7307162b49e7SJohan Hedberg 			l2cap_do_start(chan);
7308162b49e7SJohan Hedberg 	}
7309162b49e7SJohan Hedberg 
7310162b49e7SJohan Hedberg 	err = 0;
7311162b49e7SJohan Hedberg 
731202e246aeSJohan Hedberg chan_unlock:
7313162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
731402e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
731502e246aeSJohan Hedberg done:
7316162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
7317162b49e7SJohan Hedberg 	hci_dev_put(hdev);
7318162b49e7SJohan Hedberg 	return err;
7319162b49e7SJohan Hedberg }
73206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7321162b49e7SJohan Hedberg 
73220a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
73230a708f8fSGustavo F. Padovan 
7324686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
73250a708f8fSGustavo F. Padovan {
73260a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
732723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
73280a708f8fSGustavo F. Padovan 
73296ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
73300a708f8fSGustavo F. Padovan 
73310a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
733223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
733323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
733489bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
73350a708f8fSGustavo F. Padovan 			continue;
73360a708f8fSGustavo F. Padovan 
73377eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
73380a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
733943bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
73400a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
73410a708f8fSGustavo F. Padovan 			exact++;
73427eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
73430a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
734443bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
73450a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
73460a708f8fSGustavo F. Padovan 		}
73470a708f8fSGustavo F. Padovan 	}
734823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
73490a708f8fSGustavo F. Padovan 
73500a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
73510a708f8fSGustavo F. Padovan }
73520a708f8fSGustavo F. Padovan 
7353e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
7354e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
7355e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
7356e760ec12SJohan Hedberg  */
7357e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
7358327a7191SJohan Hedberg 						  struct hci_conn *hcon)
7359e760ec12SJohan Hedberg {
7360327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
7361327a7191SJohan Hedberg 
7362e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
7363e760ec12SJohan Hedberg 
7364e760ec12SJohan Hedberg 	if (c)
7365e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
7366e760ec12SJohan Hedberg 	else
7367e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
7368e760ec12SJohan Hedberg 
7369e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
7370e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
7371e760ec12SJohan Hedberg 			continue;
7372e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
7373e760ec12SJohan Hedberg 			continue;
7374327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
7375e760ec12SJohan Hedberg 			continue;
7376327a7191SJohan Hedberg 		if (src_type != c->src_type)
737754a1b626SJohan Hedberg 			continue;
7378e760ec12SJohan Hedberg 
7379e760ec12SJohan Hedberg 		l2cap_chan_hold(c);
7380e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
7381e760ec12SJohan Hedberg 		return c;
7382e760ec12SJohan Hedberg 	}
7383e760ec12SJohan Hedberg 
7384e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
7385e760ec12SJohan Hedberg 
7386e760ec12SJohan Hedberg 	return NULL;
7387e760ec12SJohan Hedberg }
7388e760ec12SJohan Hedberg 
7389539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
73900a708f8fSGustavo F. Padovan {
7391e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
73920a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
7393e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
7394e760ec12SJohan Hedberg 	u8 dst_type;
73950a708f8fSGustavo F. Padovan 
7396539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7397539c496dSJohan Hedberg 		return;
7398539c496dSJohan Hedberg 
73996ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
74000a708f8fSGustavo F. Padovan 
7401dc0f5088SJohan Hedberg 	if (status) {
7402e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7403dc0f5088SJohan Hedberg 		return;
7404ba6fc317SAndrei Emeltchenko 	}
7405dc0f5088SJohan Hedberg 
7406dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7407dc0f5088SJohan Hedberg 	if (!conn)
7408dc0f5088SJohan Hedberg 		return;
7409dc0f5088SJohan Hedberg 
7410a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
7411e760ec12SJohan Hedberg 
7412e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
7413e760ec12SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
7414e760ec12SJohan Hedberg 		return;
7415e760ec12SJohan Hedberg 
7416e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
7417e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
7418e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
7419e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
7420e760ec12SJohan Hedberg 	 */
7421327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
7422e760ec12SJohan Hedberg 	while (pchan) {
7423e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
7424e760ec12SJohan Hedberg 
7425e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
7426e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
7427e760ec12SJohan Hedberg 			goto next;
7428e760ec12SJohan Hedberg 
7429e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
7430e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
7431e760ec12SJohan Hedberg 		if (chan) {
7432e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
7433e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
7434a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
7435e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
7436e760ec12SJohan Hedberg 
7437e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
7438e760ec12SJohan Hedberg 		}
7439e760ec12SJohan Hedberg 
7440e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
7441e760ec12SJohan Hedberg next:
7442327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
7443e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
7444e760ec12SJohan Hedberg 		pchan = next;
7445e760ec12SJohan Hedberg 	}
7446e760ec12SJohan Hedberg 
7447dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
74480a708f8fSGustavo F. Padovan }
74490a708f8fSGustavo F. Padovan 
7450686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
74510a708f8fSGustavo F. Padovan {
74520a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
74530a708f8fSGustavo F. Padovan 
74540a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
74550a708f8fSGustavo F. Padovan 
7456686ebf28SUlisses Furquim 	if (!conn)
74579f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
74580a708f8fSGustavo F. Padovan 	return conn->disc_reason;
74590a708f8fSGustavo F. Padovan }
74600a708f8fSGustavo F. Padovan 
74613a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
74620a708f8fSGustavo F. Padovan {
74633a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
74643a6d576bSJohan Hedberg 		return;
74653a6d576bSJohan Hedberg 
74660a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
74670a708f8fSGustavo F. Padovan 
7468e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
74690a708f8fSGustavo F. Padovan }
74700a708f8fSGustavo F. Padovan 
74714343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
74720a708f8fSGustavo F. Padovan {
7473715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
74740a708f8fSGustavo F. Padovan 		return;
74750a708f8fSGustavo F. Padovan 
74760a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
74774343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7478ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
74797d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
74807d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
74810f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
74820a708f8fSGustavo F. Padovan 	} else {
74834343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7484c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
74850a708f8fSGustavo F. Padovan 	}
74860a708f8fSGustavo F. Padovan }
74870a708f8fSGustavo F. Padovan 
7488354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
74890a708f8fSGustavo F. Padovan {
74900a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
749148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
74920a708f8fSGustavo F. Padovan 
74930a708f8fSGustavo F. Padovan 	if (!conn)
7494354fe804SJohan Hedberg 		return;
74950a708f8fSGustavo F. Padovan 
749689d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
74970a708f8fSGustavo F. Padovan 
74983df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
74990a708f8fSGustavo F. Padovan 
75003df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
75016be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
75020a708f8fSGustavo F. Padovan 
750389d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
750489d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7505f1cb9af5SVinicius Costa Gomes 
75062338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
750778eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
750878eb2f98SAndrei Emeltchenko 			continue;
750978eb2f98SAndrei Emeltchenko 		}
751078eb2f98SAndrei Emeltchenko 
7511191eb398SJohan Hedberg 		if (!status && encrypt)
7512f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
7513f1cb9af5SVinicius Costa Gomes 
751496eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
75156be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
75160a708f8fSGustavo F. Padovan 			continue;
75170a708f8fSGustavo F. Padovan 		}
75180a708f8fSGustavo F. Padovan 
751989bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
752089bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7521d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
75224343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
75236be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
75240a708f8fSGustavo F. Padovan 			continue;
75250a708f8fSGustavo F. Padovan 		}
75260a708f8fSGustavo F. Padovan 
752789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
7528693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
752993c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
75306d3c15daSJohan Hedberg 			else
7531ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7532fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
7533fa37c1aaSJohan Hedberg 			   chan->mode != L2CAP_MODE_LE_FLOWCTL) {
75340a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7535df3c3931SJohan Hedberg 			__u16 res, stat;
75360a708f8fSGustavo F. Padovan 
7537693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
7538bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7539df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7540df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
75412dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7542df3c3931SJohan Hedberg 				} else {
7543acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7544df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7545df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7546df3c3931SJohan Hedberg 				}
75470a708f8fSGustavo F. Padovan 			} else {
7548acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7549ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7550df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7551df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
75520a708f8fSGustavo F. Padovan 			}
75530a708f8fSGustavo F. Padovan 
7554fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7555fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7556df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7557df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7558fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7559fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
75602d369359SMat Martineau 
75612d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
75622d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
75632d369359SMat Martineau 				char buf[128];
75642d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
75652d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
75662d369359SMat Martineau 					       L2CAP_CONF_REQ,
7567e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
75682d369359SMat Martineau 					       buf);
75692d369359SMat Martineau 				chan->num_conf_req++;
75702d369359SMat Martineau 			}
75710a708f8fSGustavo F. Padovan 		}
75720a708f8fSGustavo F. Padovan 
75736be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
75740a708f8fSGustavo F. Padovan 	}
75750a708f8fSGustavo F. Padovan 
75763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
75770a708f8fSGustavo F. Padovan }
75780a708f8fSGustavo F. Padovan 
75799b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
75800a708f8fSGustavo F. Padovan {
75810a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7582d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
7583d73a0988SAndrei Emeltchenko 	int len;
75840a708f8fSGustavo F. Padovan 
75851d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
7586ca8bee5dSMarcel Holtmann 	if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
75871d13a254SAndrei Emeltchenko 		goto drop;
75880a708f8fSGustavo F. Padovan 
75890a708f8fSGustavo F. Padovan 	if (!conn)
7590baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
75910a708f8fSGustavo F. Padovan 
75920a708f8fSGustavo F. Padovan 	if (!conn)
75930a708f8fSGustavo F. Padovan 		goto drop;
75940a708f8fSGustavo F. Padovan 
75950a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
75960a708f8fSGustavo F. Padovan 
7597d73a0988SAndrei Emeltchenko 	switch (flags) {
7598d73a0988SAndrei Emeltchenko 	case ACL_START:
7599d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7600d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
76010a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
76020a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
76030a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
76040a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
76050a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
76060a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76070a708f8fSGustavo F. Padovan 		}
76080a708f8fSGustavo F. Padovan 
76090a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
76100a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
76110a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
76120a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76130a708f8fSGustavo F. Padovan 			goto drop;
76140a708f8fSGustavo F. Padovan 		}
76150a708f8fSGustavo F. Padovan 
76160a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
76170a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
76180a708f8fSGustavo F. Padovan 
76190a708f8fSGustavo F. Padovan 		if (len == skb->len) {
76200a708f8fSGustavo F. Padovan 			/* Complete frame received */
76210a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
76229b4c3336SArron Wang 			return;
76230a708f8fSGustavo F. Padovan 		}
76240a708f8fSGustavo F. Padovan 
76250a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
76260a708f8fSGustavo F. Padovan 
76270a708f8fSGustavo F. Padovan 		if (skb->len > len) {
76280a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
76290a708f8fSGustavo F. Padovan 			       skb->len, len);
76300a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76310a708f8fSGustavo F. Padovan 			goto drop;
76320a708f8fSGustavo F. Padovan 		}
76330a708f8fSGustavo F. Padovan 
76340a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
76358bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
76360a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
76370a708f8fSGustavo F. Padovan 			goto drop;
76380a708f8fSGustavo F. Padovan 
76390a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
76400a708f8fSGustavo F. Padovan 					  skb->len);
76410a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7642d73a0988SAndrei Emeltchenko 		break;
7643d73a0988SAndrei Emeltchenko 
7644d73a0988SAndrei Emeltchenko 	case ACL_CONT:
76450a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
76460a708f8fSGustavo F. Padovan 
76470a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
76480a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
76490a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76500a708f8fSGustavo F. Padovan 			goto drop;
76510a708f8fSGustavo F. Padovan 		}
76520a708f8fSGustavo F. Padovan 
76530a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
76540a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
76550a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
76560a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
76570a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
76580a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
76590a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76600a708f8fSGustavo F. Padovan 			goto drop;
76610a708f8fSGustavo F. Padovan 		}
76620a708f8fSGustavo F. Padovan 
76630a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
76640a708f8fSGustavo F. Padovan 					  skb->len);
76650a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
76660a708f8fSGustavo F. Padovan 
76670a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7668c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7669c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7670c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7671c4e5bafaSJohan Hedberg 			 */
7672c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
76730a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7674c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
76750a708f8fSGustavo F. Padovan 		}
7676d73a0988SAndrei Emeltchenko 		break;
76770a708f8fSGustavo F. Padovan 	}
76780a708f8fSGustavo F. Padovan 
76790a708f8fSGustavo F. Padovan drop:
76800a708f8fSGustavo F. Padovan 	kfree_skb(skb);
76810a708f8fSGustavo F. Padovan }
76820a708f8fSGustavo F. Padovan 
7683354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
7684354fe804SJohan Hedberg 	.name		= "L2CAP",
7685539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
76863a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
7687354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
7688354fe804SJohan Hedberg };
7689354fe804SJohan Hedberg 
76900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
76910a708f8fSGustavo F. Padovan {
769223691d75SGustavo F. Padovan 	struct l2cap_chan *c;
76930a708f8fSGustavo F. Padovan 
7694333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
76950a708f8fSGustavo F. Padovan 
769623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7697eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
7698eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
769989bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
770023691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
770123691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
77020a708f8fSGustavo F. Padovan 	}
77030a708f8fSGustavo F. Padovan 
7704333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
77050a708f8fSGustavo F. Padovan 
77060a708f8fSGustavo F. Padovan 	return 0;
77070a708f8fSGustavo F. Padovan }
77080a708f8fSGustavo F. Padovan 
77098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
77100a708f8fSGustavo F. Padovan 
77110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
77120a708f8fSGustavo F. Padovan 
771364274518SGustavo F. Padovan int __init l2cap_init(void)
77140a708f8fSGustavo F. Padovan {
77150a708f8fSGustavo F. Padovan 	int err;
77160a708f8fSGustavo F. Padovan 
7717bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
77180a708f8fSGustavo F. Padovan 	if (err < 0)
77190a708f8fSGustavo F. Padovan 		return err;
77200a708f8fSGustavo F. Padovan 
7721354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
7722354fe804SJohan Hedberg 
77231120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
77241120e4bfSMarcel Holtmann 		return 0;
77251120e4bfSMarcel Holtmann 
77262d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
77272d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
77280a708f8fSGustavo F. Padovan 
77290a708f8fSGustavo F. Padovan 	return 0;
77300a708f8fSGustavo F. Padovan }
77310a708f8fSGustavo F. Padovan 
773264274518SGustavo F. Padovan void l2cap_exit(void)
77330a708f8fSGustavo F. Padovan {
77340a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7735354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
7736bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
77370a708f8fSGustavo F. Padovan }
77380a708f8fSGustavo F. Padovan 
77390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
77400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7741