xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 28261da8)
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 
17123691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1729e4425ffSGustavo F. Padovan {
17323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1749e4425ffSGustavo F. Padovan 
17523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
1767eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
17723691d75SGustavo F. Padovan 			return c;
1789e4425ffSGustavo F. Padovan 	}
179250938cbSSzymon Janc 	return NULL;
180250938cbSSzymon Janc }
1819e4425ffSGustavo F. Padovan 
1829e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1839e4425ffSGustavo F. Padovan {
18473b2ec18SGustavo F. Padovan 	int err;
18573b2ec18SGustavo F. Padovan 
186333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1879e4425ffSGustavo F. Padovan 
18823691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
18973b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
19073b2ec18SGustavo F. Padovan 		goto done;
1919e4425ffSGustavo F. Padovan 	}
1929e4425ffSGustavo F. Padovan 
19373b2ec18SGustavo F. Padovan 	if (psm) {
1949e4425ffSGustavo F. Padovan 		chan->psm = psm;
1959e4425ffSGustavo F. Padovan 		chan->sport = psm;
19673b2ec18SGustavo F. Padovan 		err = 0;
19773b2ec18SGustavo F. Padovan 	} else {
19892594a51SJohan Hedberg 		u16 p, start, end, incr;
19992594a51SJohan Hedberg 
20092594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
20192594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
20292594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
20392594a51SJohan Hedberg 			incr = 2;
20492594a51SJohan Hedberg 		} else {
20592594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
20692594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
20792594a51SJohan Hedberg 			incr = 1;
20892594a51SJohan Hedberg 		}
2099e4425ffSGustavo F. Padovan 
21073b2ec18SGustavo F. Padovan 		err = -EINVAL;
21192594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
21223691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
21373b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
21473b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
21573b2ec18SGustavo F. Padovan 				err = 0;
21673b2ec18SGustavo F. Padovan 				break;
21773b2ec18SGustavo F. Padovan 			}
21873b2ec18SGustavo F. Padovan 	}
21973b2ec18SGustavo F. Padovan 
22073b2ec18SGustavo F. Padovan done:
221333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
22273b2ec18SGustavo F. Padovan 	return err;
2239e4425ffSGustavo F. Padovan }
2246b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2259e4425ffSGustavo F. Padovan 
2269e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2279e4425ffSGustavo F. Padovan {
228333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2299e4425ffSGustavo F. Padovan 
23014824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
23114824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
23214824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
23314824308SJohan Hedberg 
2349e4425ffSGustavo F. Padovan 	chan->scid = scid;
2359e4425ffSGustavo F. Padovan 
236333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2379e4425ffSGustavo F. Padovan 
2389e4425ffSGustavo F. Padovan 	return 0;
2399e4425ffSGustavo F. Padovan }
2409e4425ffSGustavo F. Padovan 
241baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2420a708f8fSGustavo F. Padovan {
243e77af755SJohan Hedberg 	u16 cid, dyn_end;
2440a708f8fSGustavo F. Padovan 
245e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
246e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
247e77af755SJohan Hedberg 	else
248e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
249e77af755SJohan Hedberg 
250ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
251baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2520a708f8fSGustavo F. Padovan 			return cid;
2530a708f8fSGustavo F. Padovan 	}
2540a708f8fSGustavo F. Padovan 
2550a708f8fSGustavo F. Padovan 	return 0;
2560a708f8fSGustavo F. Padovan }
2570a708f8fSGustavo F. Padovan 
258f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
25989bc500eSGustavo F. Padovan {
26042d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
261badaaa00SGustavo F. Padovan 	       state_to_string(state));
262badaaa00SGustavo F. Padovan 
26389bc500eSGustavo F. Padovan 	chan->state = state;
26453f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
26589bc500eSGustavo F. Padovan }
26689bc500eSGustavo F. Padovan 
267f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
268f8e73017SGustavo Padovan 						int state, int err)
2692e0052e4SAndrei Emeltchenko {
270f8e73017SGustavo Padovan 	chan->state = state;
27153f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2722e0052e4SAndrei Emeltchenko }
2732e0052e4SAndrei Emeltchenko 
2742e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2752e0052e4SAndrei Emeltchenko {
276f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2772e0052e4SAndrei Emeltchenko }
2782e0052e4SAndrei Emeltchenko 
2794239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2804239d16fSMat Martineau {
2814239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2824239d16fSMat Martineau 	    chan->retrans_timeout) {
2834239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2844239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2854239d16fSMat Martineau 	}
2864239d16fSMat Martineau }
2874239d16fSMat Martineau 
2884239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2894239d16fSMat Martineau {
2904239d16fSMat Martineau 	__clear_retrans_timer(chan);
2914239d16fSMat Martineau 	if (chan->monitor_timeout) {
2924239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2934239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2944239d16fSMat Martineau 	}
2954239d16fSMat Martineau }
2964239d16fSMat Martineau 
297608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
298608bcc6dSMat Martineau 					       u16 seq)
299608bcc6dSMat Martineau {
300608bcc6dSMat Martineau 	struct sk_buff *skb;
301608bcc6dSMat Martineau 
302608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
303a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
304608bcc6dSMat Martineau 			return skb;
305608bcc6dSMat Martineau 	}
306608bcc6dSMat Martineau 
307608bcc6dSMat Martineau 	return NULL;
308608bcc6dSMat Martineau }
309608bcc6dSMat Martineau 
3103c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3113c588192SMat Martineau 
3123c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3133c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3143c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3153c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3163c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3173c588192SMat Martineau  * and removed from the head in constant time, without further memory
3183c588192SMat Martineau  * allocs or frees.
3193c588192SMat Martineau  */
3203c588192SMat Martineau 
3213c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3223c588192SMat Martineau {
3233c588192SMat Martineau 	size_t alloc_size, i;
3243c588192SMat Martineau 
3253c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3263c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3273c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3283c588192SMat Martineau 	 */
3293c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3303c588192SMat Martineau 
3316da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3323c588192SMat Martineau 	if (!seq_list->list)
3333c588192SMat Martineau 		return -ENOMEM;
3343c588192SMat Martineau 
3353c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3363c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3373c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3393c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau 
3413c588192SMat Martineau 	return 0;
3423c588192SMat Martineau }
3433c588192SMat Martineau 
3443c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3453c588192SMat Martineau {
3463c588192SMat Martineau 	kfree(seq_list->list);
3473c588192SMat Martineau }
3483c588192SMat Martineau 
3493c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3503c588192SMat Martineau 					   u16 seq)
3513c588192SMat Martineau {
3523c588192SMat Martineau 	/* Constant-time check for list membership */
3533c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3543c588192SMat Martineau }
3553c588192SMat Martineau 
35603a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3573c588192SMat Martineau {
35803a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3593c588192SMat Martineau 	u16 mask = seq_list->mask;
3603c588192SMat Martineau 
3613c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3623c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3633c588192SMat Martineau 
3643c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3653c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3663c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3673c588192SMat Martineau 	}
3683c588192SMat Martineau 
3693c588192SMat Martineau 	return seq;
3703c588192SMat Martineau }
3713c588192SMat Martineau 
3723c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3733c588192SMat Martineau {
3743c588192SMat Martineau 	u16 i;
375f522ae36SGustavo Padovan 
376f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
377f522ae36SGustavo Padovan 		return;
378f522ae36SGustavo Padovan 
3793c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3803c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3813c588192SMat Martineau 
3823c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3833c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3843c588192SMat Martineau }
3853c588192SMat Martineau 
3863c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3873c588192SMat Martineau {
3883c588192SMat Martineau 	u16 mask = seq_list->mask;
3893c588192SMat Martineau 
3903c588192SMat Martineau 	/* All appends happen in constant time */
3913c588192SMat Martineau 
392f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
393f522ae36SGustavo Padovan 		return;
394f522ae36SGustavo Padovan 
3953c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3963c588192SMat Martineau 		seq_list->head = seq;
3973c588192SMat Martineau 	else
3983c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3993c588192SMat Martineau 
4003c588192SMat Martineau 	seq_list->tail = seq;
4013c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4023c588192SMat Martineau }
4033c588192SMat Martineau 
404721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
405ab07801dSGustavo F. Padovan {
406721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
407721c4181SGustavo F. Padovan 					       chan_timer.work);
4083df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
409ab07801dSGustavo F. Padovan 	int reason;
410ab07801dSGustavo F. Padovan 
411e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
412ab07801dSGustavo F. Padovan 
4133df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4146be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
415ab07801dSGustavo F. Padovan 
41689bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
417ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
41889bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
419ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
420ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
421ab07801dSGustavo F. Padovan 	else
422ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
423ab07801dSGustavo F. Padovan 
4240f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
425ab07801dSGustavo F. Padovan 
4266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
427ab07801dSGustavo F. Padovan 
42880b98027SGustavo Padovan 	chan->ops->close(chan);
4293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4303df91ea2SAndrei Emeltchenko 
431371fd835SUlisses Furquim 	l2cap_chan_put(chan);
432ab07801dSGustavo F. Padovan }
433ab07801dSGustavo F. Padovan 
434eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4350a708f8fSGustavo F. Padovan {
43648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4370a708f8fSGustavo F. Padovan 
43848454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
43948454079SGustavo F. Padovan 	if (!chan)
44048454079SGustavo F. Padovan 		return NULL;
4410a708f8fSGustavo F. Padovan 
442c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
443c03b355eSAndrei Emeltchenko 
444ff714119SJohan Hedberg 	/* Set default lock nesting level */
445ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
446ff714119SJohan Hedberg 
447333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
44823691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
449333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
45023691d75SGustavo F. Padovan 
451721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
452ab07801dSGustavo F. Padovan 
45389bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
45489bc500eSGustavo F. Padovan 
455144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
45671ba0e56SGustavo F. Padovan 
4572827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4582827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4592827011fSMat Martineau 
460eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
461abc545b8SSzymon Janc 
46248454079SGustavo F. Padovan 	return chan;
4630a708f8fSGustavo F. Padovan }
4646b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4650a708f8fSGustavo F. Padovan 
466144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4676ff5abbfSGustavo F. Padovan {
468144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
469144ad330SSyam Sidhardhan 
4704af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4714af66c69SJaganath Kanakkassery 
472333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
47323691d75SGustavo F. Padovan 	list_del(&chan->global_l);
474333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
47523691d75SGustavo F. Padovan 
4764af66c69SJaganath Kanakkassery 	kfree(chan);
4776ff5abbfSGustavo F. Padovan }
4786ff5abbfSGustavo F. Padovan 
47930648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
48030648372SJaganath Kanakkassery {
4812c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
48230648372SJaganath Kanakkassery 
483144ad330SSyam Sidhardhan 	kref_get(&c->kref);
48430648372SJaganath Kanakkassery }
48530648372SJaganath Kanakkassery 
48630648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
48730648372SJaganath Kanakkassery {
4882c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
48930648372SJaganath Kanakkassery 
490144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
49130648372SJaganath Kanakkassery }
4926b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
49330648372SJaganath Kanakkassery 
494bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
495bd4b1653SAndrei Emeltchenko {
496bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
497bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
498bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
499bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5006a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5016a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
502c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
503bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5046a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5056a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5066a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5076a5e8165SJukka Rissanen 	chan->conf_state = 0;
508bd4b1653SAndrei Emeltchenko 
509bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
510bd4b1653SAndrei Emeltchenko }
5116b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
512bd4b1653SAndrei Emeltchenko 
513ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
51438319713SJohan Hedberg {
5150ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5160ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5170ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
518ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
519fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
520fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
52196cd8eaaSLuiz Augusto von Dentz 	/* Give enough credits for a full packet */
52296cd8eaaSLuiz Augusto von Dentz 	chan->rx_credits = (chan->imtu / chan->mps) + 1;
5230ce43ce6SJohan Hedberg 
5240ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
52538319713SJohan Hedberg }
52638319713SJohan Hedberg 
52793c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5280a708f8fSGustavo F. Padovan {
5290a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
530097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5310a708f8fSGustavo F. Padovan 
5329f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5330a708f8fSGustavo F. Padovan 
5348c1d787bSGustavo F. Padovan 	chan->conn = conn;
5350a708f8fSGustavo F. Padovan 
5365491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5375491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
5380a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
539fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
54021626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
5410c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
5425491120eSAndrei Emeltchenko 		break;
5435491120eSAndrei Emeltchenko 
5445491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5450a708f8fSGustavo F. Padovan 		/* Connectionless socket */
546fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
547fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5480c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5495491120eSAndrei Emeltchenko 		break;
5505491120eSAndrei Emeltchenko 
5512338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
5522338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
553416fa752SAndrei Emeltchenko 		break;
554416fa752SAndrei Emeltchenko 
5555491120eSAndrei Emeltchenko 	default:
5560a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
557fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
558fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5590c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5600a708f8fSGustavo F. Padovan 	}
5610a708f8fSGustavo F. Padovan 
5628f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5638f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5648f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5658f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5668f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5678936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5688f7975b1SAndrei Emeltchenko 
569371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
570baa7e1faSGustavo F. Padovan 
571c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
572c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
573c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
5745ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
5755ee9891dSJohan Hedberg 
5763df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
577643162a8SAndrei Emeltchenko }
578643162a8SAndrei Emeltchenko 
579466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
580643162a8SAndrei Emeltchenko {
581643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
582643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5833df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5840a708f8fSGustavo F. Padovan }
5850a708f8fSGustavo F. Padovan 
586466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5870a708f8fSGustavo F. Padovan {
5888c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5890a708f8fSGustavo F. Padovan 
590c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5910a708f8fSGustavo F. Padovan 
59249d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
59349d11741SJohan Hedberg 	       state_to_string(chan->state));
5940a708f8fSGustavo F. Padovan 
59572847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
59672847ce0SJohan Hedberg 
5970a708f8fSGustavo F. Padovan 	if (conn) {
59856f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
599baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6003df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6013d57dc68SGustavo F. Padovan 
602371fd835SUlisses Furquim 		l2cap_chan_put(chan);
603baa7e1faSGustavo F. Padovan 
6048c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6053cabbfdaSAndrei Emeltchenko 
606c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
607c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
608c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
609c16900cfSJohan Hedberg 		 */
610c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
611c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
61276a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
61356f60984SAndrei Emeltchenko 
61456f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
61556f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6160a708f8fSGustavo F. Padovan 	}
6170a708f8fSGustavo F. Padovan 
618419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
619419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
620419e08c1SAndrei Emeltchenko 
621419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
622419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
623419e08c1SAndrei Emeltchenko 	}
624419e08c1SAndrei Emeltchenko 
6252827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6266ff5abbfSGustavo F. Padovan 		return;
6272ead70b8SGustavo F. Padovan 
628ee556f66SGustavo Padovan 	switch(chan->mode) {
629ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
630ee556f66SGustavo Padovan 		break;
6310a708f8fSGustavo F. Padovan 
63238319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
633177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
63438319713SJohan Hedberg 		break;
63538319713SJohan Hedberg 
636ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6371a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6381a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6391a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6400a708f8fSGustavo F. Padovan 
641f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6420a708f8fSGustavo F. Padovan 
6433c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6443c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
645ee556f66SGustavo Padovan 
646ee556f66SGustavo Padovan 		/* fall through */
647ee556f66SGustavo Padovan 
648ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
649ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
650ee556f66SGustavo Padovan 		break;
6510a708f8fSGustavo F. Padovan 	}
652ee556f66SGustavo Padovan 
653ee556f66SGustavo Padovan 	return;
6540a708f8fSGustavo F. Padovan }
6556b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
6560a708f8fSGustavo F. Padovan 
657f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
658387a33e3SJohan Hedberg {
659f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
660f3d82d0cSJohan Hedberg 					       id_addr_update_work);
661f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
662387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
663387a33e3SJohan Hedberg 
664387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
665387a33e3SJohan Hedberg 
666387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
667387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
668387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
669a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
670387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
671387a33e3SJohan Hedberg 	}
672387a33e3SJohan Hedberg 
673387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
674387a33e3SJohan Hedberg }
675387a33e3SJohan Hedberg 
67627e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
67727e2d4c8SJohan Hedberg {
67827e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
67927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
68027e2d4c8SJohan Hedberg 	u16 result;
68127e2d4c8SJohan Hedberg 
68227e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
683571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
68427e2d4c8SJohan Hedberg 	else
685571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
68627e2d4c8SJohan Hedberg 
68727e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
68827e2d4c8SJohan Hedberg 
68927e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
69027e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
6913916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
6920cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
69327e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
69427e2d4c8SJohan Hedberg 
69527e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
69627e2d4c8SJohan Hedberg 		       &rsp);
69727e2d4c8SJohan Hedberg }
69827e2d4c8SJohan Hedberg 
699791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
700791d60f7SJohan Hedberg {
701791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
702791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
703791d60f7SJohan Hedberg 	u16 result;
704791d60f7SJohan Hedberg 
705791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
706791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
707791d60f7SJohan Hedberg 	else
708791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
709791d60f7SJohan Hedberg 
710791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
711791d60f7SJohan Hedberg 
712791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
713791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
714791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
715dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
716791d60f7SJohan Hedberg 
717791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
718791d60f7SJohan Hedberg }
719791d60f7SJohan Hedberg 
7200f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
7214519de9aSGustavo F. Padovan {
7224519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7234519de9aSGustavo F. Padovan 
7247eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
7254519de9aSGustavo F. Padovan 
72689bc500eSGustavo F. Padovan 	switch (chan->state) {
7274519de9aSGustavo F. Padovan 	case BT_LISTEN:
728c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7294519de9aSGustavo F. Padovan 		break;
7304519de9aSGustavo F. Padovan 
7314519de9aSGustavo F. Padovan 	case BT_CONNECTED:
7324519de9aSGustavo F. Padovan 	case BT_CONFIG:
7337b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
7348d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7355e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
7364519de9aSGustavo F. Padovan 		} else
7374519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
7384519de9aSGustavo F. Padovan 		break;
7394519de9aSGustavo F. Padovan 
7404519de9aSGustavo F. Padovan 	case BT_CONNECT2:
741791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
742791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
743791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
74427e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
74527e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7464519de9aSGustavo F. Padovan 		}
7474519de9aSGustavo F. Padovan 
7484519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7494519de9aSGustavo F. Padovan 		break;
7504519de9aSGustavo F. Padovan 
7514519de9aSGustavo F. Padovan 	case BT_CONNECT:
7524519de9aSGustavo F. Padovan 	case BT_DISCONN:
7534519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7544519de9aSGustavo F. Padovan 		break;
7554519de9aSGustavo F. Padovan 
7564519de9aSGustavo F. Padovan 	default:
757c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7584519de9aSGustavo F. Padovan 		break;
7594519de9aSGustavo F. Padovan 	}
7604519de9aSGustavo F. Padovan }
7616b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
7624519de9aSGustavo F. Padovan 
7634343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7640a708f8fSGustavo F. Padovan {
7656a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7666a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7674343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7680a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7697d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
7700a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7710a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7720a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7730a708f8fSGustavo F. Padovan 		default:
7740a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7750a708f8fSGustavo F. Padovan 		}
7766a974b50SMarcel Holtmann 		break;
7773124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
778dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
7793124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7803124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7813124b843SMarcel Holtmann 		}
7827d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
7837d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
7843124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7853124b843SMarcel Holtmann 		else
7863124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7873124b843SMarcel Holtmann 		break;
7886a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
789dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
7904343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7914343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
7920a708f8fSGustavo F. Padovan 
7937d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
7947d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
7950a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
7960a708f8fSGustavo F. Padovan 			else
7970a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
7986a974b50SMarcel Holtmann 		}
7996a974b50SMarcel Holtmann 		/* fall through */
8006a974b50SMarcel Holtmann 	default:
8014343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8020a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8037d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8040a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
8050a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8060a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
8070a708f8fSGustavo F. Padovan 		default:
8080a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8090a708f8fSGustavo F. Padovan 		}
8106a974b50SMarcel Holtmann 		break;
8110a708f8fSGustavo F. Padovan 	}
8120a708f8fSGustavo F. Padovan }
8130a708f8fSGustavo F. Padovan 
8140a708f8fSGustavo F. Padovan /* Service level security */
815e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
8160a708f8fSGustavo F. Padovan {
8178c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8180a708f8fSGustavo F. Padovan 	__u8 auth_type;
8190a708f8fSGustavo F. Padovan 
820a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
821a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
822a17de2feSJohan Hedberg 
8234343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
8240a708f8fSGustavo F. Padovan 
825e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
826e7cafc45SJohan Hedberg 				 initiator);
8270a708f8fSGustavo F. Padovan }
8280a708f8fSGustavo F. Padovan 
829b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
8300a708f8fSGustavo F. Padovan {
8310a708f8fSGustavo F. Padovan 	u8 id;
8320a708f8fSGustavo F. Padovan 
8330a708f8fSGustavo F. Padovan 	/* Get next available identificator.
8340a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
8350a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
8360a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
8370a708f8fSGustavo F. Padovan 	 */
8380a708f8fSGustavo F. Padovan 
8395a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
8400a708f8fSGustavo F. Padovan 
8410a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
8420a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
8430a708f8fSGustavo F. Padovan 
8440a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
8450a708f8fSGustavo F. Padovan 
8465a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
8470a708f8fSGustavo F. Padovan 
8480a708f8fSGustavo F. Padovan 	return id;
8490a708f8fSGustavo F. Padovan }
8500a708f8fSGustavo F. Padovan 
8512d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8522d792818SGustavo Padovan 			   void *data)
8530a708f8fSGustavo F. Padovan {
8540a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8550a708f8fSGustavo F. Padovan 	u8 flags;
8560a708f8fSGustavo F. Padovan 
8570a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8580a708f8fSGustavo F. Padovan 
8590a708f8fSGustavo F. Padovan 	if (!skb)
8600a708f8fSGustavo F. Padovan 		return;
8610a708f8fSGustavo F. Padovan 
862f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
863f6af675eSSteven Walter 	 * not support auto-flushing packets) */
864f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
865f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
8660a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8670a708f8fSGustavo F. Padovan 	else
8680a708f8fSGustavo F. Padovan 		flags = ACL_START;
8690a708f8fSGustavo F. Padovan 
87014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8715e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
87214b12d0bSJaikumar Ganesh 
87373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8740a708f8fSGustavo F. Padovan }
8750a708f8fSGustavo F. Padovan 
87602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
87702b0fbb9SMat Martineau {
87802b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
87902b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
88002b0fbb9SMat Martineau }
88102b0fbb9SMat Martineau 
88273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
88373d80debSLuiz Augusto von Dentz {
88473d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
88573d80debSLuiz Augusto von Dentz 	u16 flags;
88673d80debSLuiz Augusto von Dentz 
88773d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
88873d80debSLuiz Augusto von Dentz 	       skb->priority);
88973d80debSLuiz Augusto von Dentz 
890d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
891d5f8a75dSMat Martineau 		if (chan->hs_hchan)
892d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
893d5f8a75dSMat Martineau 		else
894d5f8a75dSMat Martineau 			kfree_skb(skb);
895d5f8a75dSMat Martineau 
896d5f8a75dSMat Martineau 		return;
897d5f8a75dSMat Martineau 	}
898d5f8a75dSMat Martineau 
899f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
900f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
901f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
902f6af675eSSteven Walter 	 */
903f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
904f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
905f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
90673d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
90773d80debSLuiz Augusto von Dentz 	else
90873d80debSLuiz Augusto von Dentz 		flags = ACL_START;
90973d80debSLuiz Augusto von Dentz 
91073d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
91173d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
9120a708f8fSGustavo F. Padovan }
9130a708f8fSGustavo F. Padovan 
914b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
915b5c6aaedSMat Martineau {
916b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
917b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
918b5c6aaedSMat Martineau 
919b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
920b5c6aaedSMat Martineau 		/* S-Frame */
921b5c6aaedSMat Martineau 		control->sframe = 1;
922b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
923b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
924b5c6aaedSMat Martineau 
925b5c6aaedSMat Martineau 		control->sar = 0;
926b5c6aaedSMat Martineau 		control->txseq = 0;
927b5c6aaedSMat Martineau 	} else {
928b5c6aaedSMat Martineau 		/* I-Frame */
929b5c6aaedSMat Martineau 		control->sframe = 0;
930b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
931b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
932b5c6aaedSMat Martineau 
933b5c6aaedSMat Martineau 		control->poll = 0;
934b5c6aaedSMat Martineau 		control->super = 0;
935b5c6aaedSMat Martineau 	}
936b5c6aaedSMat Martineau }
937b5c6aaedSMat Martineau 
938b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
939b5c6aaedSMat Martineau {
940b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
941b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
942b5c6aaedSMat Martineau 
943b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
944b5c6aaedSMat Martineau 		/* S-Frame */
945b5c6aaedSMat Martineau 		control->sframe = 1;
946b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
947b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
948b5c6aaedSMat Martineau 
949b5c6aaedSMat Martineau 		control->sar = 0;
950b5c6aaedSMat Martineau 		control->txseq = 0;
951b5c6aaedSMat Martineau 	} else {
952b5c6aaedSMat Martineau 		/* I-Frame */
953b5c6aaedSMat Martineau 		control->sframe = 0;
954b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
955b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
956b5c6aaedSMat Martineau 
957b5c6aaedSMat Martineau 		control->poll = 0;
958b5c6aaedSMat Martineau 		control->super = 0;
959b5c6aaedSMat Martineau 	}
960b5c6aaedSMat Martineau }
961b5c6aaedSMat Martineau 
962b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
963b5c6aaedSMat Martineau 				    struct sk_buff *skb)
964b5c6aaedSMat Martineau {
965b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
966b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
967a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
968cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
969b5c6aaedSMat Martineau 	} else {
970b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
971a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
972cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
973b5c6aaedSMat Martineau 	}
974b5c6aaedSMat Martineau }
975b5c6aaedSMat Martineau 
976b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
977b5c6aaedSMat Martineau {
978b5c6aaedSMat Martineau 	u32 packed;
979b5c6aaedSMat Martineau 
980b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
981b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
982b5c6aaedSMat Martineau 
983b5c6aaedSMat Martineau 	if (control->sframe) {
984b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
985b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
986b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
987b5c6aaedSMat Martineau 	} else {
988b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
989b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
990b5c6aaedSMat Martineau 	}
991b5c6aaedSMat Martineau 
992b5c6aaedSMat Martineau 	return packed;
993b5c6aaedSMat Martineau }
994b5c6aaedSMat Martineau 
995b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
996b5c6aaedSMat Martineau {
997b5c6aaedSMat Martineau 	u16 packed;
998b5c6aaedSMat Martineau 
999b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1000b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1001b5c6aaedSMat Martineau 
1002b5c6aaedSMat Martineau 	if (control->sframe) {
1003b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1004b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1005b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1006b5c6aaedSMat Martineau 	} else {
1007b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1008b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1009b5c6aaedSMat Martineau 	}
1010b5c6aaedSMat Martineau 
1011b5c6aaedSMat Martineau 	return packed;
1012b5c6aaedSMat Martineau }
1013b5c6aaedSMat Martineau 
1014b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1015b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1016b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1017b5c6aaedSMat Martineau {
1018b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1019b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1020b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1021b5c6aaedSMat Martineau 	} else {
1022b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1023b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1024b5c6aaedSMat Martineau 	}
1025b5c6aaedSMat Martineau }
1026b5c6aaedSMat Martineau 
1027ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1028ba7aa64fSGustavo Padovan {
1029ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1030ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1031ba7aa64fSGustavo Padovan 	else
1032ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1033ba7aa64fSGustavo Padovan }
1034ba7aa64fSGustavo Padovan 
1035a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1036a67d7f6fSMat Martineau 					       u32 control)
10370a708f8fSGustavo F. Padovan {
10380a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
10390a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1040ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
10410a708f8fSGustavo F. Padovan 
10420a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
104303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
10440a708f8fSGustavo F. Padovan 
1045a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
10460a708f8fSGustavo F. Padovan 
10470a708f8fSGustavo F. Padovan 	if (!skb)
1048a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
10490a708f8fSGustavo F. Padovan 
10504df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
10510a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1052fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
105388843ab0SAndrei Emeltchenko 
1054a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1055a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1056a67d7f6fSMat Martineau 	else
1057a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10580a708f8fSGustavo F. Padovan 
105947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1060a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
106103a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10620a708f8fSGustavo F. Padovan 	}
10630a708f8fSGustavo F. Padovan 
106473d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1065a67d7f6fSMat Martineau 	return skb;
1066a67d7f6fSMat Martineau }
1067a67d7f6fSMat Martineau 
1068a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1069a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1070a67d7f6fSMat Martineau {
1071a67d7f6fSMat Martineau 	struct sk_buff *skb;
1072a67d7f6fSMat Martineau 	u32 control_field;
1073a67d7f6fSMat Martineau 
1074a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1075a67d7f6fSMat Martineau 
1076a67d7f6fSMat Martineau 	if (!control->sframe)
1077a67d7f6fSMat Martineau 		return;
1078a67d7f6fSMat Martineau 
1079b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1080b99e13adSMat Martineau 		return;
1081b99e13adSMat Martineau 
1082a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1083a67d7f6fSMat Martineau 	    !control->poll)
1084a67d7f6fSMat Martineau 		control->final = 1;
1085a67d7f6fSMat Martineau 
1086a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1087a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1088a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1089a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1090a67d7f6fSMat Martineau 
1091a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1092a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1093a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1094a67d7f6fSMat Martineau 	}
1095a67d7f6fSMat Martineau 
1096a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1097a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1098a67d7f6fSMat Martineau 
1099a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1100a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1101a67d7f6fSMat Martineau 	else
1102a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1103a67d7f6fSMat Martineau 
1104a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1105a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
110673d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
11070a708f8fSGustavo F. Padovan }
11080a708f8fSGustavo F. Padovan 
1109c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11100a708f8fSGustavo F. Padovan {
1111c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
11120a708f8fSGustavo F. Padovan 
1113c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1114c9e3d5e0SMat Martineau 
1115c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1116c9e3d5e0SMat Martineau 	control.sframe = 1;
1117c9e3d5e0SMat Martineau 	control.poll = poll;
1118c9e3d5e0SMat Martineau 
1119c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1120c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1121c9e3d5e0SMat Martineau 	else
1122c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1123c9e3d5e0SMat Martineau 
1124c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1125c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
11260a708f8fSGustavo F. Padovan }
11270a708f8fSGustavo F. Padovan 
1128b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
11290a708f8fSGustavo F. Padovan {
11305ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
11315ff6f34dSJohan Hedberg 		return true;
11325ff6f34dSJohan Hedberg 
1133c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
11340a708f8fSGustavo F. Padovan }
11350a708f8fSGustavo F. Padovan 
113693c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
113793c3e8f5SAndrei Emeltchenko {
113893c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11391df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
11401df7b17aSMarcel Holtmann 	bool amp_available = false;
114193c3e8f5SAndrei Emeltchenko 
11420bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
11431df7b17aSMarcel Holtmann 		return false;
11441df7b17aSMarcel Holtmann 
11450bd49fc7SJohan Hedberg 	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
11461df7b17aSMarcel Holtmann 		return false;
11471df7b17aSMarcel Holtmann 
11481df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
11491df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
11501df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
11511df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
11521df7b17aSMarcel Holtmann 			amp_available = true;
11531df7b17aSMarcel Holtmann 			break;
11541df7b17aSMarcel Holtmann 		}
11551df7b17aSMarcel Holtmann 	}
11561df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
11571df7b17aSMarcel Holtmann 
11581df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11591df7b17aSMarcel Holtmann 		return amp_available;
1160848566b3SMarcel Holtmann 
116193c3e8f5SAndrei Emeltchenko 	return false;
116293c3e8f5SAndrei Emeltchenko }
116393c3e8f5SAndrei Emeltchenko 
11645ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11655ce66b59SAndrei Emeltchenko {
11665ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11675ce66b59SAndrei Emeltchenko 	return true;
11685ce66b59SAndrei Emeltchenko }
11695ce66b59SAndrei Emeltchenko 
11702766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11719b27f350SAndrei Emeltchenko {
11729b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11739b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11749b27f350SAndrei Emeltchenko 
11759b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11769b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11779b27f350SAndrei Emeltchenko 
11789b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11799b27f350SAndrei Emeltchenko 
11809b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11819b27f350SAndrei Emeltchenko 
11829b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11839b27f350SAndrei Emeltchenko }
11849b27f350SAndrei Emeltchenko 
11858eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11868eb200bdSMat Martineau {
11878eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11888eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11898eb200bdSMat Martineau 	req.psm  = chan->psm;
11908eb200bdSMat Martineau 	req.amp_id = amp_id;
11918eb200bdSMat Martineau 
11928eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
11938eb200bdSMat Martineau 
11948eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
11958eb200bdSMat Martineau 		       sizeof(req), &req);
11968eb200bdSMat Martineau }
11978eb200bdSMat Martineau 
119802b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
119902b0fbb9SMat Martineau {
120002b0fbb9SMat Martineau 	struct sk_buff *skb;
120102b0fbb9SMat Martineau 
120202b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
120302b0fbb9SMat Martineau 
120402b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
120502b0fbb9SMat Martineau 		return;
120602b0fbb9SMat Martineau 
120702b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
120802b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
120902b0fbb9SMat Martineau 	__clear_ack_timer(chan);
121002b0fbb9SMat Martineau 
121102b0fbb9SMat Martineau 	chan->retry_count = 0;
121202b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
1213a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.retries)
1214a4368ff3SJohan Hedberg 			bt_cb(skb)->l2cap.retries = 1;
121502b0fbb9SMat Martineau 		else
121602b0fbb9SMat Martineau 			break;
121702b0fbb9SMat Martineau 	}
121802b0fbb9SMat Martineau 
121902b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
122002b0fbb9SMat Martineau 
122102b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
122202b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
122302b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
122402b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
122502b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
122602b0fbb9SMat Martineau 
122702b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
122802b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
122902b0fbb9SMat Martineau 
123002b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
123102b0fbb9SMat Martineau }
123202b0fbb9SMat Martineau 
12335f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
12345f3847a4SMat Martineau {
12355f3847a4SMat Martineau 	u8 move_role = chan->move_role;
12365f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
12375f3847a4SMat Martineau 
12385f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
12395f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
12405f3847a4SMat Martineau 
12415f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
12425f3847a4SMat Martineau 		return;
12435f3847a4SMat Martineau 
12445f3847a4SMat Martineau 	switch (move_role) {
12455f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
12465f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
12475f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
12485f3847a4SMat Martineau 		break;
12495f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
12505f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
12515f3847a4SMat Martineau 		break;
12525f3847a4SMat Martineau 	}
12535f3847a4SMat Martineau }
12545f3847a4SMat Martineau 
12559f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12569f0caeb1SVinicius Costa Gomes {
1257315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1258315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1259315917e0SJohan Hedberg 	 * procedure is complete.
1260315917e0SJohan Hedberg 	 */
1261315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1262315917e0SJohan Hedberg 		return;
1263315917e0SJohan Hedberg 
12642827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12659f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12669f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12679f0caeb1SVinicius Costa Gomes 
12680ce43ce6SJohan Hedberg 	if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits)
12690ce43ce6SJohan Hedberg 		chan->ops->suspend(chan);
1270177f8f2bSJohan Hedberg 
127154a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12729f0caeb1SVinicius Costa Gomes 
127354a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12749f0caeb1SVinicius Costa Gomes }
12759f0caeb1SVinicius Costa Gomes 
1276f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1277f1496deeSJohan Hedberg {
1278f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1279f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1280f1496deeSJohan Hedberg 
1281595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1282595177f3SJohan Hedberg 		return;
1283595177f3SJohan Hedberg 
1284ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1285fe149310SLuiz Augusto von Dentz 
1286f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1287f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1288f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
12893916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
12900cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1291f1496deeSJohan Hedberg 
1292f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1293f1496deeSJohan Hedberg 
1294f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1295f1496deeSJohan Hedberg 		       sizeof(req), &req);
1296f1496deeSJohan Hedberg }
1297f1496deeSJohan Hedberg 
1298f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1299f1496deeSJohan Hedberg {
1300f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1301f1496deeSJohan Hedberg 
1302f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1303f1496deeSJohan Hedberg 		return;
1304f1496deeSJohan Hedberg 
1305f1496deeSJohan Hedberg 	if (!chan->psm) {
1306f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1307f1496deeSJohan Hedberg 		return;
1308f1496deeSJohan Hedberg 	}
1309f1496deeSJohan Hedberg 
1310f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1311f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1312f1496deeSJohan Hedberg }
1313f1496deeSJohan Hedberg 
131493c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
131593c3e8f5SAndrei Emeltchenko {
131693c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
131793c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
131893c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1319f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1320f1496deeSJohan Hedberg 		l2cap_le_start(chan);
132193c3e8f5SAndrei Emeltchenko 	} else {
132293c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
132393c3e8f5SAndrei Emeltchenko 	}
132493c3e8f5SAndrei Emeltchenko }
132593c3e8f5SAndrei Emeltchenko 
1326aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
13270a708f8fSGustavo F. Padovan {
13280a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1329aeaeb4bbSJohan Hedberg 
1330aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1331aeaeb4bbSJohan Hedberg 		return;
1332aeaeb4bbSJohan Hedberg 
1333dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
13340a708f8fSGustavo F. Padovan 
13350a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
13360a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
13370a708f8fSGustavo F. Padovan 
1338ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
13390a708f8fSGustavo F. Padovan 
13402d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
13412d792818SGustavo Padovan 		       sizeof(req), &req);
13420a708f8fSGustavo F. Padovan }
1343aeaeb4bbSJohan Hedberg 
1344693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1345693cd8ceSMarcel Holtmann {
1346693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1347693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1348693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1349693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1350693cd8ceSMarcel Holtmann 	 *
1351693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1352693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1353693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1354693cd8ceSMarcel Holtmann 	 */
1355693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1356693cd8ceSMarcel Holtmann 		hcon->enc_key_size > HCI_MIN_ENC_KEY_SIZE);
1357693cd8ceSMarcel Holtmann }
1358693cd8ceSMarcel Holtmann 
1359aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1360aeaeb4bbSJohan Hedberg {
1361aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1362aeaeb4bbSJohan Hedberg 
1363aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1364aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1365aeaeb4bbSJohan Hedberg 		return;
1366aeaeb4bbSJohan Hedberg 	}
1367aeaeb4bbSJohan Hedberg 
1368aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1369aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1370aeaeb4bbSJohan Hedberg 		return;
1371aeaeb4bbSJohan Hedberg 	}
1372aeaeb4bbSJohan Hedberg 
1373aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1374aeaeb4bbSJohan Hedberg 		return;
1375aeaeb4bbSJohan Hedberg 
1376693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1377693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1378693cd8ceSMarcel Holtmann 		return;
1379693cd8ceSMarcel Holtmann 
1380693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1381aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1382693cd8ceSMarcel Holtmann 	else
1383693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
13840a708f8fSGustavo F. Padovan }
13850a708f8fSGustavo F. Padovan 
13860a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
13870a708f8fSGustavo F. Padovan {
13880a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
13890a708f8fSGustavo F. Padovan 	if (!disable_ertm)
13900a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
13910a708f8fSGustavo F. Padovan 
13920a708f8fSGustavo F. Padovan 	switch (mode) {
13930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
13940a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
13950a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
13960a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
13970a708f8fSGustavo F. Padovan 	default:
13980a708f8fSGustavo F. Padovan 		return 0x00;
13990a708f8fSGustavo F. Padovan 	}
14000a708f8fSGustavo F. Padovan }
14010a708f8fSGustavo F. Padovan 
14025e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
14030a708f8fSGustavo F. Padovan {
14045e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
14050a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
14060a708f8fSGustavo F. Padovan 
14070a708f8fSGustavo F. Padovan 	if (!conn)
14080a708f8fSGustavo F. Padovan 		return;
14090a708f8fSGustavo F. Padovan 
1410aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
14111a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
14121a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
14131a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
14140a708f8fSGustavo F. Padovan 	}
14150a708f8fSGustavo F. Padovan 
14162338a7e0SJohan Hedberg 	if (chan->scid == L2CAP_CID_A2MP) {
1417d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1418416fa752SAndrei Emeltchenko 		return;
1419416fa752SAndrei Emeltchenko 	}
1420416fa752SAndrei Emeltchenko 
1421fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1422fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
14232d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
14242d792818SGustavo Padovan 		       sizeof(req), &req);
14250a708f8fSGustavo F. Padovan 
1426f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
14270a708f8fSGustavo F. Padovan }
14280a708f8fSGustavo F. Padovan 
14290a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
14300a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
14310a708f8fSGustavo F. Padovan {
14323df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
14330a708f8fSGustavo F. Padovan 
14340a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
14350a708f8fSGustavo F. Padovan 
14363df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
14370a708f8fSGustavo F. Padovan 
14383df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
14396be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
14400a708f8fSGustavo F. Padovan 
1441715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1442aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
14436be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
14440a708f8fSGustavo F. Padovan 			continue;
14450a708f8fSGustavo F. Padovan 		}
14460a708f8fSGustavo F. Padovan 
144789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1448e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1449b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
14506be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14510a708f8fSGustavo F. Padovan 				continue;
14520a708f8fSGustavo F. Padovan 			}
14530a708f8fSGustavo F. Padovan 
1454c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1455c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1456c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
14570f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
14586be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14590a708f8fSGustavo F. Padovan 				continue;
14600a708f8fSGustavo F. Padovan 			}
14610a708f8fSGustavo F. Padovan 
1462693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
146393c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1464693cd8ceSMarcel Holtmann 			else
1465693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
14660a708f8fSGustavo F. Padovan 
146789bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
14680a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
14690a708f8fSGustavo F. Padovan 			char buf[128];
1470fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1471fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
14720a708f8fSGustavo F. Padovan 
1473e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1474bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1475dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1476dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
14772dc4e510SGustavo Padovan 					chan->ops->defer(chan);
14780a708f8fSGustavo F. Padovan 
14790a708f8fSGustavo F. Padovan 				} else {
1480acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1481dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1482dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
14830a708f8fSGustavo F. Padovan 				}
14840a708f8fSGustavo F. Padovan 			} else {
1485dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1486dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
14870a708f8fSGustavo F. Padovan 			}
14880a708f8fSGustavo F. Padovan 
1489fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1490fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
14910a708f8fSGustavo F. Padovan 
1492c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
14930a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
14946be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14950a708f8fSGustavo F. Padovan 				continue;
14960a708f8fSGustavo F. Padovan 			}
14970a708f8fSGustavo F. Padovan 
1498c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
14990a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1500e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
150173ffa904SGustavo F. Padovan 			chan->num_conf_req++;
15020a708f8fSGustavo F. Padovan 		}
15030a708f8fSGustavo F. Padovan 
15046be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15050a708f8fSGustavo F. Padovan 	}
15060a708f8fSGustavo F. Padovan 
15073df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15080a708f8fSGustavo F. Padovan }
15090a708f8fSGustavo F. Padovan 
1510b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1511b62f328bSVille Tervo {
1512cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1513dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1514b62f328bSVille Tervo 
1515e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1516b62f328bSVille Tervo 
1517e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1518e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1519e760ec12SJohan Hedberg 	 */
1520e760ec12SJohan Hedberg 	if (hcon->out)
1521e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1522cc8dba2bSMarcel Holtmann 
152380afeb6cSMarcel Holtmann 	/* For LE slave connections, make sure the connection interval
152480afeb6cSMarcel Holtmann 	 * is in the range of the minium and maximum interval that has
152580afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
152680afeb6cSMarcel Holtmann 	 * the connection update procedure.
152780afeb6cSMarcel Holtmann 	 */
152840bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
152980afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
153080afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
153180afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
153280afeb6cSMarcel Holtmann 
153380afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
153480afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
153580afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
153680afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
153780afeb6cSMarcel Holtmann 
153880afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
153980afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
154080afeb6cSMarcel Holtmann 	}
1541b62f328bSVille Tervo }
1542b62f328bSVille Tervo 
15430a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
15440a708f8fSGustavo F. Padovan {
154548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1546cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
15470a708f8fSGustavo F. Padovan 
15480a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15490a708f8fSGustavo F. Padovan 
1550aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1551aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1552aeaeb4bbSJohan Hedberg 
1553e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1554e760ec12SJohan Hedberg 
15553df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1556baa7e1faSGustavo F. Padovan 
15576be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15580a708f8fSGustavo F. Padovan 
15592338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
1560416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1561416fa752SAndrei Emeltchenko 			continue;
1562416fa752SAndrei Emeltchenko 		}
1563416fa752SAndrei Emeltchenko 
1564cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1565f1496deeSJohan Hedberg 			l2cap_le_start(chan);
156663128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1567aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
156874e75740SGustavo Padovan 				l2cap_chan_ready(chan);
15691c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1570fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15711c244f79SGustavo Padovan 		}
15720a708f8fSGustavo F. Padovan 
15736be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15740a708f8fSGustavo F. Padovan 	}
15750a708f8fSGustavo F. Padovan 
15763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
157761a939c6SJohan Hedberg 
157879a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
157979a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
158079a05727SJohan Hedberg 
158161a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
15820a708f8fSGustavo F. Padovan }
15830a708f8fSGustavo F. Padovan 
15840a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15850a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15860a708f8fSGustavo F. Padovan {
158748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15880a708f8fSGustavo F. Padovan 
15890a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15900a708f8fSGustavo F. Padovan 
15913df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15920a708f8fSGustavo F. Padovan 
15933df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1594ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
15951d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
15960a708f8fSGustavo F. Padovan 	}
15970a708f8fSGustavo F. Padovan 
15983df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15990a708f8fSGustavo F. Padovan }
16000a708f8fSGustavo F. Padovan 
1601f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
16020a708f8fSGustavo F. Padovan {
1603f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1604030013d8SGustavo F. Padovan 					       info_timer.work);
16050a708f8fSGustavo F. Padovan 
16060a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
16070a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
16080a708f8fSGustavo F. Padovan 
16090a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
16100a708f8fSGustavo F. Padovan }
16110a708f8fSGustavo F. Padovan 
16122c8e1411SDavid Herrmann /*
16132c8e1411SDavid Herrmann  * l2cap_user
16142c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
16152c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
16162c8e1411SDavid Herrmann  * during unregistration.
16172c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
16182c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
16192c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16202c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
16212c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16222c8e1411SDavid Herrmann  * any time if they don't.
16232c8e1411SDavid Herrmann  */
16242c8e1411SDavid Herrmann 
16252c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16262c8e1411SDavid Herrmann {
16272c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16282c8e1411SDavid Herrmann 	int ret;
16292c8e1411SDavid Herrmann 
16302c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
16312c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
16322c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16332c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
16342c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
16352c8e1411SDavid Herrmann 	 * here, too. */
16362c8e1411SDavid Herrmann 
16372c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16382c8e1411SDavid Herrmann 
1639835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
16402c8e1411SDavid Herrmann 		ret = -EINVAL;
16412c8e1411SDavid Herrmann 		goto out_unlock;
16422c8e1411SDavid Herrmann 	}
16432c8e1411SDavid Herrmann 
16442c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
16452c8e1411SDavid Herrmann 	if (!conn->hchan) {
16462c8e1411SDavid Herrmann 		ret = -ENODEV;
16472c8e1411SDavid Herrmann 		goto out_unlock;
16482c8e1411SDavid Herrmann 	}
16492c8e1411SDavid Herrmann 
16502c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
16512c8e1411SDavid Herrmann 	if (ret)
16522c8e1411SDavid Herrmann 		goto out_unlock;
16532c8e1411SDavid Herrmann 
16542c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16552c8e1411SDavid Herrmann 	ret = 0;
16562c8e1411SDavid Herrmann 
16572c8e1411SDavid Herrmann out_unlock:
16582c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16592c8e1411SDavid Herrmann 	return ret;
16602c8e1411SDavid Herrmann }
16612c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16622c8e1411SDavid Herrmann 
16632c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16642c8e1411SDavid Herrmann {
16652c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16662c8e1411SDavid Herrmann 
16672c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16682c8e1411SDavid Herrmann 
1669835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
16702c8e1411SDavid Herrmann 		goto out_unlock;
16712c8e1411SDavid Herrmann 
1672ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
16732c8e1411SDavid Herrmann 	user->remove(conn, user);
16742c8e1411SDavid Herrmann 
16752c8e1411SDavid Herrmann out_unlock:
16762c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16772c8e1411SDavid Herrmann }
16782c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16792c8e1411SDavid Herrmann 
16802c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16812c8e1411SDavid Herrmann {
16822c8e1411SDavid Herrmann 	struct l2cap_user *user;
16832c8e1411SDavid Herrmann 
16842c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16852c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1686ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
16872c8e1411SDavid Herrmann 		user->remove(conn, user);
16882c8e1411SDavid Herrmann 	}
16892c8e1411SDavid Herrmann }
16902c8e1411SDavid Herrmann 
16915d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
16925d3de7dfSVinicius Costa Gomes {
16935d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
16945d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
16955d3de7dfSVinicius Costa Gomes 
16965d3de7dfSVinicius Costa Gomes 	if (!conn)
16975d3de7dfSVinicius Costa Gomes 		return;
16985d3de7dfSVinicius Costa Gomes 
16995d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
17005d3de7dfSVinicius Costa Gomes 
17015d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
17025d3de7dfSVinicius Costa Gomes 
170361a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
17047ab56c3aSJukka Taimisto 
17057ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
17067ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
17077ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
17087ab56c3aSJukka Taimisto 	 */
17097ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
17107ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
171161a939c6SJohan Hedberg 
1712f3d82d0cSJohan Hedberg 	if (work_pending(&conn->id_addr_update_work))
1713f3d82d0cSJohan Hedberg 		cancel_work_sync(&conn->id_addr_update_work);
1714f3d82d0cSJohan Hedberg 
17152c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
17162c8e1411SDavid Herrmann 
1717e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1718e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1719e31fb860SJohan Hedberg 
17203df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17213df91ea2SAndrei Emeltchenko 
17225d3de7dfSVinicius Costa Gomes 	/* Kill channels */
17235d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
172461d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
17256be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17266be36555SAndrei Emeltchenko 
17275d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
17286be36555SAndrei Emeltchenko 
17296be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17306be36555SAndrei Emeltchenko 
173180b98027SGustavo Padovan 		chan->ops->close(chan);
173261d6ef3eSMat Martineau 		l2cap_chan_put(chan);
17335d3de7dfSVinicius Costa Gomes 	}
17345d3de7dfSVinicius Costa Gomes 
17353df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17363df91ea2SAndrei Emeltchenko 
173773d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
173873d80debSLuiz Augusto von Dentz 
17395d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1740127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
17415d3de7dfSVinicius Costa Gomes 
17425d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
17439c903e37SDavid Herrmann 	conn->hchan = NULL;
17449c903e37SDavid Herrmann 	l2cap_conn_put(conn);
17455d3de7dfSVinicius Costa Gomes }
17465d3de7dfSVinicius Costa Gomes 
17479c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17489c903e37SDavid Herrmann {
17499c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17509c903e37SDavid Herrmann 
17519c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17529c903e37SDavid Herrmann 	kfree(conn);
17539c903e37SDavid Herrmann }
17549c903e37SDavid Herrmann 
175551bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
17569c903e37SDavid Herrmann {
17579c903e37SDavid Herrmann 	kref_get(&conn->ref);
175851bb8457SJohan Hedberg 	return conn;
17599c903e37SDavid Herrmann }
17609c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
17619c903e37SDavid Herrmann 
17629c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
17639c903e37SDavid Herrmann {
17649c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
17659c903e37SDavid Herrmann }
17669c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
17679c903e37SDavid Herrmann 
17680a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
17690a708f8fSGustavo F. Padovan 
1770c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
17710a708f8fSGustavo F. Padovan  * Returns closest match.
17720a708f8fSGustavo F. Padovan  */
1773c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1774c2287681SIdo Yariv 						   bdaddr_t *src,
1775bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1776bf20fd4eSJohan Hedberg 						   u8 link_type)
17770a708f8fSGustavo F. Padovan {
177823691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
17790a708f8fSGustavo F. Padovan 
178023691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
17810a708f8fSGustavo F. Padovan 
178223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
178389bc500eSGustavo F. Padovan 		if (state && c->state != state)
17840a708f8fSGustavo F. Padovan 			continue;
17850a708f8fSGustavo F. Padovan 
1786bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1787bf20fd4eSJohan Hedberg 			continue;
1788bf20fd4eSJohan Hedberg 
1789bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1790bf20fd4eSJohan Hedberg 			continue;
1791bf20fd4eSJohan Hedberg 
179223691d75SGustavo F. Padovan 		if (c->psm == psm) {
1793c2287681SIdo Yariv 			int src_match, dst_match;
1794c2287681SIdo Yariv 			int src_any, dst_any;
1795c2287681SIdo Yariv 
17960a708f8fSGustavo F. Padovan 			/* Exact match. */
17977eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
17987eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1799c2287681SIdo Yariv 			if (src_match && dst_match) {
1800a24cce14SJohan Hedberg 				l2cap_chan_hold(c);
1801a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
180223691d75SGustavo F. Padovan 				return c;
180323691d75SGustavo F. Padovan 			}
18040a708f8fSGustavo F. Padovan 
18050a708f8fSGustavo F. Padovan 			/* Closest match */
18067eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18077eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1808c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1809c2287681SIdo Yariv 			    (src_any && dst_any))
181023691d75SGustavo F. Padovan 				c1 = c;
18110a708f8fSGustavo F. Padovan 		}
18120a708f8fSGustavo F. Padovan 	}
18130a708f8fSGustavo F. Padovan 
1814a24cce14SJohan Hedberg 	if (c1)
1815a24cce14SJohan Hedberg 		l2cap_chan_hold(c1);
1816a24cce14SJohan Hedberg 
181723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18180a708f8fSGustavo F. Padovan 
181923691d75SGustavo F. Padovan 	return c1;
18200a708f8fSGustavo F. Padovan }
18210a708f8fSGustavo F. Padovan 
1822721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
18230a708f8fSGustavo F. Padovan {
1824721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1825721c4181SGustavo F. Padovan 					       monitor_timer.work);
18260a708f8fSGustavo F. Padovan 
1827525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
18280a708f8fSGustavo F. Padovan 
18296be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
18306be36555SAndrei Emeltchenko 
183180909e04SMat Martineau 	if (!chan->conn) {
18326be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
18338d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
18340a708f8fSGustavo F. Padovan 		return;
18350a708f8fSGustavo F. Padovan 	}
18360a708f8fSGustavo F. Padovan 
1837401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
18380a708f8fSGustavo F. Padovan 
18396be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
18408d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
18410a708f8fSGustavo F. Padovan }
18420a708f8fSGustavo F. Padovan 
1843721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
18440a708f8fSGustavo F. Padovan {
1845721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1846721c4181SGustavo F. Padovan 					       retrans_timer.work);
18470a708f8fSGustavo F. Padovan 
184849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
18490a708f8fSGustavo F. Padovan 
18506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
18516be36555SAndrei Emeltchenko 
185280909e04SMat Martineau 	if (!chan->conn) {
185380909e04SMat Martineau 		l2cap_chan_unlock(chan);
185480909e04SMat Martineau 		l2cap_chan_put(chan);
185580909e04SMat Martineau 		return;
185680909e04SMat Martineau 	}
18570a708f8fSGustavo F. Padovan 
1858401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
18596be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
18608d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
18610a708f8fSGustavo F. Padovan }
18620a708f8fSGustavo F. Padovan 
1863d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
18643733937dSMat Martineau 				 struct sk_buff_head *skbs)
18650a708f8fSGustavo F. Padovan {
18660a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
18673733937dSMat Martineau 	struct l2cap_ctrl *control;
18680a708f8fSGustavo F. Padovan 
18693733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
18703733937dSMat Martineau 
1871b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1872b99e13adSMat Martineau 		return;
1873b99e13adSMat Martineau 
18743733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
18753733937dSMat Martineau 
18763733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
18773733937dSMat Martineau 
18783733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
18793733937dSMat Martineau 
1880a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1881a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
18823733937dSMat Martineau 
18833733937dSMat Martineau 		control->reqseq = 0;
18843733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
18853733937dSMat Martineau 
18863733937dSMat Martineau 		__pack_control(chan, control, skb);
18870a708f8fSGustavo F. Padovan 
188847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
18893733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
18903733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
18910a708f8fSGustavo F. Padovan 		}
18920a708f8fSGustavo F. Padovan 
18934343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
18940a708f8fSGustavo F. Padovan 
1895b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
18963733937dSMat Martineau 
1897836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
18983733937dSMat Martineau 		chan->frames_sent++;
18990a708f8fSGustavo F. Padovan 	}
19000a708f8fSGustavo F. Padovan }
19010a708f8fSGustavo F. Padovan 
190267c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
19030a708f8fSGustavo F. Padovan {
19040a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
190518a48e76SMat Martineau 	struct l2cap_ctrl *control;
190618a48e76SMat Martineau 	int sent = 0;
190718a48e76SMat Martineau 
190818a48e76SMat Martineau 	BT_DBG("chan %p", chan);
19090a708f8fSGustavo F. Padovan 
191089bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
19110a708f8fSGustavo F. Padovan 		return -ENOTCONN;
19120a708f8fSGustavo F. Padovan 
191394122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
191494122bbeSMat Martineau 		return 0;
191594122bbeSMat Martineau 
1916b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1917b99e13adSMat Martineau 		return 0;
1918b99e13adSMat Martineau 
191918a48e76SMat Martineau 	while (chan->tx_send_head &&
192018a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
192118a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
19220a708f8fSGustavo F. Padovan 
192318a48e76SMat Martineau 		skb = chan->tx_send_head;
19240a708f8fSGustavo F. Padovan 
1925a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1926a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
19270a708f8fSGustavo F. Padovan 
1928e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
192918a48e76SMat Martineau 			control->final = 1;
1930e2ab4353SGustavo F. Padovan 
193118a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
193218a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
193318a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
19340a708f8fSGustavo F. Padovan 
193518a48e76SMat Martineau 		__pack_control(chan, control, skb);
19360a708f8fSGustavo F. Padovan 
193747d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
193818a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
193918a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19400a708f8fSGustavo F. Padovan 		}
19410a708f8fSGustavo F. Padovan 
194218a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
194318a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
194418a48e76SMat Martineau 		 */
194518a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
194618a48e76SMat Martineau 
194718a48e76SMat Martineau 		if (!tx_skb)
194818a48e76SMat Martineau 			break;
19490a708f8fSGustavo F. Padovan 
19501a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
19510a708f8fSGustavo F. Padovan 
1952836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
19536a026610SGustavo F. Padovan 		chan->unacked_frames++;
19546a026610SGustavo F. Padovan 		chan->frames_sent++;
195518a48e76SMat Martineau 		sent++;
19560a708f8fSGustavo F. Padovan 
195758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
195858d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
19590a708f8fSGustavo F. Padovan 		else
196058d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
196118a48e76SMat Martineau 
196218a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
1963b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
19640a708f8fSGustavo F. Padovan 	}
19650a708f8fSGustavo F. Padovan 
1966b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
1967b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
196818a48e76SMat Martineau 
196918a48e76SMat Martineau 	return sent;
19700a708f8fSGustavo F. Padovan }
19710a708f8fSGustavo F. Padovan 
1972e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1973e1fbd4c1SMat Martineau {
1974e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1975e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1976e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1977e1fbd4c1SMat Martineau 	u16 seq;
1978e1fbd4c1SMat Martineau 
1979e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1980e1fbd4c1SMat Martineau 
1981e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1982e1fbd4c1SMat Martineau 		return;
1983e1fbd4c1SMat Martineau 
1984b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1985b99e13adSMat Martineau 		return;
1986b99e13adSMat Martineau 
1987e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1988e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1989e1fbd4c1SMat Martineau 
1990e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1991e1fbd4c1SMat Martineau 		if (!skb) {
1992e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
1993e1fbd4c1SMat Martineau 			       seq);
1994e1fbd4c1SMat Martineau 			continue;
1995e1fbd4c1SMat Martineau 		}
1996e1fbd4c1SMat Martineau 
1997a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
1998a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
1999e1fbd4c1SMat Martineau 
2000e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2001a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2002e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
20035e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2004e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2005e1fbd4c1SMat Martineau 			break;
2006e1fbd4c1SMat Martineau 		}
2007e1fbd4c1SMat Martineau 
2008e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2009e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2010e1fbd4c1SMat Martineau 			control.final = 1;
2011e1fbd4c1SMat Martineau 		else
2012e1fbd4c1SMat Martineau 			control.final = 0;
2013e1fbd4c1SMat Martineau 
2014e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2015e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2016e1fbd4c1SMat Martineau 			 * writeable copy
2017e1fbd4c1SMat Martineau 			 */
20188bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2019e1fbd4c1SMat Martineau 		} else {
20208bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2021e1fbd4c1SMat Martineau 		}
2022e1fbd4c1SMat Martineau 
2023e1fbd4c1SMat Martineau 		if (!tx_skb) {
2024e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2025e1fbd4c1SMat Martineau 			break;
2026e1fbd4c1SMat Martineau 		}
2027e1fbd4c1SMat Martineau 
2028e1fbd4c1SMat Martineau 		/* Update skb contents */
2029e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2030e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2031e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2032e1fbd4c1SMat Martineau 		} else {
2033e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2034e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2035e1fbd4c1SMat Martineau 		}
2036e1fbd4c1SMat Martineau 
203713cac152SLukasz Rymanowski 		/* Update FCS */
2038e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
203913cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
204013cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
204113cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
204213cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2043e1fbd4c1SMat Martineau 		}
2044e1fbd4c1SMat Martineau 
2045e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2046e1fbd4c1SMat Martineau 
2047e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2048e1fbd4c1SMat Martineau 
2049e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2050e1fbd4c1SMat Martineau 	}
2051e1fbd4c1SMat Martineau }
2052e1fbd4c1SMat Martineau 
2053f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2054f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2055f80842a8SMat Martineau {
2056f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2057f80842a8SMat Martineau 
2058f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2059f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2060f80842a8SMat Martineau }
2061f80842a8SMat Martineau 
2062d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2063d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2064d2a7ac5dSMat Martineau {
2065e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2066e1fbd4c1SMat Martineau 
2067e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2068e1fbd4c1SMat Martineau 
2069e1fbd4c1SMat Martineau 	if (control->poll)
2070e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2071e1fbd4c1SMat Martineau 
2072e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2073e1fbd4c1SMat Martineau 
2074e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2075e1fbd4c1SMat Martineau 		return;
2076e1fbd4c1SMat Martineau 
2077e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2078e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2079a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2080e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2081e1fbd4c1SMat Martineau 				break;
2082e1fbd4c1SMat Martineau 		}
2083e1fbd4c1SMat Martineau 
2084e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2085e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2086e1fbd4c1SMat Martineau 				break;
2087e1fbd4c1SMat Martineau 
2088e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2089a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2090e1fbd4c1SMat Martineau 		}
2091e1fbd4c1SMat Martineau 
2092e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2093e1fbd4c1SMat Martineau 	}
2094d2a7ac5dSMat Martineau }
2095d2a7ac5dSMat Martineau 
2096b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2097b17e73bbSSzymon Janc {
20980a0aba42SMat Martineau 	struct l2cap_ctrl control;
20990a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
21000a0aba42SMat Martineau 					 chan->last_acked_seq);
21010a0aba42SMat Martineau 	int threshold;
21020a0aba42SMat Martineau 
21030a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
21040a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
21050a0aba42SMat Martineau 
21060a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
21070a0aba42SMat Martineau 	control.sframe = 1;
21080a0aba42SMat Martineau 
21090a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
21100a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2111b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
21120a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
21130a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
21140a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
21150a0aba42SMat Martineau 	} else {
21160a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
21170a0aba42SMat Martineau 			l2cap_ertm_send(chan);
21180a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
21190a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
21200a0aba42SMat Martineau 				frames_to_ack = 0;
21210a0aba42SMat Martineau 		}
21220a0aba42SMat Martineau 
2123c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
21240a0aba42SMat Martineau 		 * Calculate without mul or div
21250a0aba42SMat Martineau 		 */
2126c20f8e35SMat Martineau 		threshold = chan->ack_win;
21270a0aba42SMat Martineau 		threshold += threshold << 1;
21280a0aba42SMat Martineau 		threshold >>= 2;
21290a0aba42SMat Martineau 
2130b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
21310a0aba42SMat Martineau 		       threshold);
21320a0aba42SMat Martineau 
21330a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
21340a0aba42SMat Martineau 			__clear_ack_timer(chan);
21350a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
21360a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
21370a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
21380a0aba42SMat Martineau 			frames_to_ack = 0;
21390a0aba42SMat Martineau 		}
21400a0aba42SMat Martineau 
21410a0aba42SMat Martineau 		if (frames_to_ack)
21420a0aba42SMat Martineau 			__set_ack_timer(chan);
21430a0aba42SMat Martineau 	}
2144b17e73bbSSzymon Janc }
2145b17e73bbSSzymon Janc 
214604124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
214704124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
214804124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
21490a708f8fSGustavo F. Padovan {
21500952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
21510a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
215290338947SGustavo Padovan 	int sent = 0;
21530a708f8fSGustavo F. Padovan 
2154cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
21550a708f8fSGustavo F. Padovan 		return -EFAULT;
21560a708f8fSGustavo F. Padovan 
21570a708f8fSGustavo F. Padovan 	sent += count;
21580a708f8fSGustavo F. Padovan 	len  -= count;
21590a708f8fSGustavo F. Padovan 
21600a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
21610a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
21620a708f8fSGustavo F. Padovan 	while (len) {
2163fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2164fbe00700SGustavo Padovan 
21650a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
21660a708f8fSGustavo F. Padovan 
2167d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
216890338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2169fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2170fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
21712f7719ceSAndrei Emeltchenko 
2172fbe00700SGustavo Padovan 		*frag = tmp;
2173fbe00700SGustavo Padovan 
2174cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2175cbbd26b8SAl Viro 				   &msg->msg_iter))
21760a708f8fSGustavo F. Padovan 			return -EFAULT;
21770a708f8fSGustavo F. Padovan 
21780a708f8fSGustavo F. Padovan 		sent += count;
21790a708f8fSGustavo F. Padovan 		len  -= count;
21800a708f8fSGustavo F. Padovan 
21812d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
21822d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
21832d0ed3d5SGustavo Padovan 
21840a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
21850a708f8fSGustavo F. Padovan 	}
21860a708f8fSGustavo F. Padovan 
21870a708f8fSGustavo F. Padovan 	return sent;
21880a708f8fSGustavo F. Padovan }
21890a708f8fSGustavo F. Padovan 
21905e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
21918d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
21920a708f8fSGustavo F. Padovan {
21938c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
21940a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
219503a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
21960a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
21970a708f8fSGustavo F. Padovan 
21988d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
21998d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
22000a708f8fSGustavo F. Padovan 
22010a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
22022f7719ceSAndrei Emeltchenko 
2203d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
220490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
220590338947SGustavo Padovan 	if (IS_ERR(skb))
220690338947SGustavo Padovan 		return skb;
22070a708f8fSGustavo F. Padovan 
22080a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22094df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2210fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2211daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
221243b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
22130a708f8fSGustavo F. Padovan 
22140952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22150a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22160a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22170a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22180a708f8fSGustavo F. Padovan 	}
22190a708f8fSGustavo F. Padovan 	return skb;
22200a708f8fSGustavo F. Padovan }
22210a708f8fSGustavo F. Padovan 
22225e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
22238d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
22240a708f8fSGustavo F. Padovan {
22258c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22260a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2227f2ba7faeSGustavo Padovan 	int err, count;
22280a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22290a708f8fSGustavo F. Padovan 
2230b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
22310a708f8fSGustavo F. Padovan 
2232f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
22332f7719ceSAndrei Emeltchenko 
2234d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
223590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
223690338947SGustavo Padovan 	if (IS_ERR(skb))
223790338947SGustavo Padovan 		return skb;
22380a708f8fSGustavo F. Padovan 
22390a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22404df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2241fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
22426ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
22430a708f8fSGustavo F. Padovan 
22440952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22450a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22460a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22470a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22480a708f8fSGustavo F. Padovan 	}
22490a708f8fSGustavo F. Padovan 	return skb;
22500a708f8fSGustavo F. Padovan }
22510a708f8fSGustavo F. Padovan 
2252ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2253ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
225494122bbeSMat Martineau 					       u16 sdulen)
22550a708f8fSGustavo F. Padovan {
22568c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22570a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2258e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
22590a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22600a708f8fSGustavo F. Padovan 
2261b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
22620a708f8fSGustavo F. Padovan 
22630a708f8fSGustavo F. Padovan 	if (!conn)
22640a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
22650a708f8fSGustavo F. Padovan 
2266ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2267e4ca6d98SAndrei Emeltchenko 
22680a708f8fSGustavo F. Padovan 	if (sdulen)
226903a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
22700a708f8fSGustavo F. Padovan 
227147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
227203a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
22730a708f8fSGustavo F. Padovan 
22740a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
22752f7719ceSAndrei Emeltchenko 
2276d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
227790338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
227890338947SGustavo Padovan 	if (IS_ERR(skb))
227990338947SGustavo Padovan 		return skb;
22800a708f8fSGustavo F. Padovan 
22810a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22824df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2283fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
22840a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
228588843ab0SAndrei Emeltchenko 
228618a48e76SMat Martineau 	/* Control header is populated later */
228718a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
228818a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
228918a48e76SMat Martineau 	else
229018a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
229188843ab0SAndrei Emeltchenko 
22920a708f8fSGustavo F. Padovan 	if (sdulen)
229303a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
22940a708f8fSGustavo F. Padovan 
22950952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22960a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22970a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22980a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22990a708f8fSGustavo F. Padovan 	}
23000a708f8fSGustavo F. Padovan 
2301a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2302a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
23030a708f8fSGustavo F. Padovan 	return skb;
23040a708f8fSGustavo F. Padovan }
23050a708f8fSGustavo F. Padovan 
230694122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
230794122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
230894122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
23090a708f8fSGustavo F. Padovan {
23100a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
231194122bbeSMat Martineau 	u16 sdu_len;
231294122bbeSMat Martineau 	size_t pdu_len;
231394122bbeSMat Martineau 	u8 sar;
23140a708f8fSGustavo F. Padovan 
2315b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
23160a708f8fSGustavo F. Padovan 
231794122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
231894122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
231994122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
232094122bbeSMat Martineau 	 */
232194122bbeSMat Martineau 
232294122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
232394122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
232494122bbeSMat Martineau 
2325a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2326a549574dSMat Martineau 	if (!chan->hs_hcon)
232794122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
232894122bbeSMat Martineau 
232994122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
233035d401dfSGustavo Padovan 	if (chan->fcs)
233135d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
233235d401dfSGustavo Padovan 
2333ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
233494122bbeSMat Martineau 
233594122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
233694122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
233794122bbeSMat Martineau 
233894122bbeSMat Martineau 	if (len <= pdu_len) {
233994122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
234094122bbeSMat Martineau 		sdu_len = 0;
234194122bbeSMat Martineau 		pdu_len = len;
234294122bbeSMat Martineau 	} else {
234394122bbeSMat Martineau 		sar = L2CAP_SAR_START;
234494122bbeSMat Martineau 		sdu_len = len;
234594122bbeSMat Martineau 	}
23460a708f8fSGustavo F. Padovan 
23470a708f8fSGustavo F. Padovan 	while (len > 0) {
234894122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
23490a708f8fSGustavo F. Padovan 
23500a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
235194122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
23520a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
23530a708f8fSGustavo F. Padovan 		}
23540a708f8fSGustavo F. Padovan 
2355a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
235694122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
23570a708f8fSGustavo F. Padovan 
235894122bbeSMat Martineau 		len -= pdu_len;
2359069cb270SLukasz Rymanowski 		if (sdu_len)
236094122bbeSMat Martineau 			sdu_len = 0;
236194122bbeSMat Martineau 
236294122bbeSMat Martineau 		if (len <= pdu_len) {
236394122bbeSMat Martineau 			sar = L2CAP_SAR_END;
236494122bbeSMat Martineau 			pdu_len = len;
236594122bbeSMat Martineau 		} else {
236694122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
236794122bbeSMat Martineau 		}
236894122bbeSMat Martineau 	}
236994122bbeSMat Martineau 
2370f0f62799SGustavo Padovan 	return 0;
23710a708f8fSGustavo F. Padovan }
23720a708f8fSGustavo F. Padovan 
2373177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2374177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2375177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2376177f8f2bSJohan Hedberg {
2377177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2378177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2379177f8f2bSJohan Hedberg 	int err, count, hlen;
2380177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2381177f8f2bSJohan Hedberg 
2382177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2383177f8f2bSJohan Hedberg 
2384177f8f2bSJohan Hedberg 	if (!conn)
2385177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2386177f8f2bSJohan Hedberg 
2387177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2388177f8f2bSJohan Hedberg 
2389177f8f2bSJohan Hedberg 	if (sdulen)
2390177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2391177f8f2bSJohan Hedberg 
2392177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2393177f8f2bSJohan Hedberg 
2394d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2395177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2396177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2397177f8f2bSJohan Hedberg 		return skb;
2398177f8f2bSJohan Hedberg 
2399177f8f2bSJohan Hedberg 	/* Create L2CAP header */
24004df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2401177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2402177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2403177f8f2bSJohan Hedberg 
2404177f8f2bSJohan Hedberg 	if (sdulen)
2405177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2406177f8f2bSJohan Hedberg 
2407177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2408177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2409177f8f2bSJohan Hedberg 		kfree_skb(skb);
2410177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2411177f8f2bSJohan Hedberg 	}
2412177f8f2bSJohan Hedberg 
2413177f8f2bSJohan Hedberg 	return skb;
2414177f8f2bSJohan Hedberg }
2415177f8f2bSJohan Hedberg 
2416177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2417177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2418177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2419177f8f2bSJohan Hedberg {
2420177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2421177f8f2bSJohan Hedberg 	size_t pdu_len;
2422177f8f2bSJohan Hedberg 	u16 sdu_len;
2423177f8f2bSJohan Hedberg 
2424177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2425177f8f2bSJohan Hedberg 
2426177f8f2bSJohan Hedberg 	sdu_len = len;
242772c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2428177f8f2bSJohan Hedberg 
2429177f8f2bSJohan Hedberg 	while (len > 0) {
2430177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2431177f8f2bSJohan Hedberg 			pdu_len = len;
2432177f8f2bSJohan Hedberg 
2433177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2434177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2435177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2436177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2437177f8f2bSJohan Hedberg 		}
2438177f8f2bSJohan Hedberg 
2439177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2440177f8f2bSJohan Hedberg 
2441177f8f2bSJohan Hedberg 		len -= pdu_len;
2442177f8f2bSJohan Hedberg 
2443177f8f2bSJohan Hedberg 		if (sdu_len) {
2444177f8f2bSJohan Hedberg 			sdu_len = 0;
2445177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2446177f8f2bSJohan Hedberg 		}
2447177f8f2bSJohan Hedberg 	}
2448177f8f2bSJohan Hedberg 
2449177f8f2bSJohan Hedberg 	return 0;
2450177f8f2bSJohan Hedberg }
2451177f8f2bSJohan Hedberg 
24528a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
24538a505b7fSLuiz Augusto von Dentz {
24548a505b7fSLuiz Augusto von Dentz 	int sent = 0;
24558a505b7fSLuiz Augusto von Dentz 
24568a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
24578a505b7fSLuiz Augusto von Dentz 
24588a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
24598a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
24608a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
24618a505b7fSLuiz Augusto von Dentz 		sent++;
24628a505b7fSLuiz Augusto von Dentz 	}
24638a505b7fSLuiz Augusto von Dentz 
24648a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
24658a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
24668a505b7fSLuiz Augusto von Dentz }
24678a505b7fSLuiz Augusto von Dentz 
24688d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
24699a91a04aSGustavo F. Padovan {
24709a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
24719a91a04aSGustavo F. Padovan 	int err;
247294122bbeSMat Martineau 	struct sk_buff_head seg_queue;
24739a91a04aSGustavo F. Padovan 
247431e8ce80SSeung-Woo Kim 	if (!chan->conn)
247531e8ce80SSeung-Woo Kim 		return -ENOTCONN;
247631e8ce80SSeung-Woo Kim 
24779a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2478715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
24798d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
24809a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
24819a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
24829a91a04aSGustavo F. Padovan 
2483ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2484ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2485ede81a2aSAndrzej Kaczmarek 		 */
2486ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2487ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2488ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2489ede81a2aSAndrzej Kaczmarek 		}
2490ede81a2aSAndrzej Kaczmarek 
24919a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
24929a91a04aSGustavo F. Padovan 		return len;
24939a91a04aSGustavo F. Padovan 	}
24949a91a04aSGustavo F. Padovan 
24959a91a04aSGustavo F. Padovan 	switch (chan->mode) {
249638319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
2497177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2498177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2499177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2500177f8f2bSJohan Hedberg 
2501177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2502177f8f2bSJohan Hedberg 
2503177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2504177f8f2bSJohan Hedberg 
2505177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2506177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2507177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2508177f8f2bSJohan Hedberg 		}
2509177f8f2bSJohan Hedberg 
2510177f8f2bSJohan Hedberg 		if (err)
2511177f8f2bSJohan Hedberg 			return err;
2512177f8f2bSJohan Hedberg 
2513177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2514177f8f2bSJohan Hedberg 
25158a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2516177f8f2bSJohan Hedberg 
2517177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2518177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2519177f8f2bSJohan Hedberg 
2520177f8f2bSJohan Hedberg 		err = len;
2521177f8f2bSJohan Hedberg 
2522177f8f2bSJohan Hedberg 		break;
2523177f8f2bSJohan Hedberg 
2524fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
25259a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
25269a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
25279a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
25289a91a04aSGustavo F. Padovan 
25299a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
25308d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
25319a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25329a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25339a91a04aSGustavo F. Padovan 
2534ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2535ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2536ede81a2aSAndrzej Kaczmarek 		 */
2537ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2538ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2539ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2540ede81a2aSAndrzej Kaczmarek 		}
2541ede81a2aSAndrzej Kaczmarek 
25429a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25439a91a04aSGustavo F. Padovan 		err = len;
25449a91a04aSGustavo F. Padovan 		break;
25459a91a04aSGustavo F. Padovan 
25469a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
25479a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
254894122bbeSMat Martineau 		/* Check outgoing MTU */
254994122bbeSMat Martineau 		if (len > chan->omtu) {
255094122bbeSMat Martineau 			err = -EMSGSIZE;
25519a91a04aSGustavo F. Padovan 			break;
25529a91a04aSGustavo F. Padovan 		}
25539a91a04aSGustavo F. Padovan 
255494122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
255594122bbeSMat Martineau 
255694122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
255794122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
255894122bbeSMat Martineau 		 * allocation.
255994122bbeSMat Martineau 		 */
256094122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
256194122bbeSMat Martineau 
256294122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
256394122bbeSMat Martineau 		 * check that it is still connected.
256494122bbeSMat Martineau 		 */
256594122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
256694122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
256794122bbeSMat Martineau 			err = -ENOTCONN;
25689a91a04aSGustavo F. Padovan 		}
25699a91a04aSGustavo F. Padovan 
257094122bbeSMat Martineau 		if (err)
257194122bbeSMat Martineau 			break;
257294122bbeSMat Martineau 
25733733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2574d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
25753733937dSMat Martineau 		else
2576d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
257794122bbeSMat Martineau 
25789a91a04aSGustavo F. Padovan 		err = len;
25799a91a04aSGustavo F. Padovan 
258094122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
258194122bbeSMat Martineau 		 * seg_queue and need to be purged.
258294122bbeSMat Martineau 		 */
258394122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
25849a91a04aSGustavo F. Padovan 		break;
25859a91a04aSGustavo F. Padovan 
25869a91a04aSGustavo F. Padovan 	default:
25879a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
25889a91a04aSGustavo F. Padovan 		err = -EBADFD;
25899a91a04aSGustavo F. Padovan 	}
25909a91a04aSGustavo F. Padovan 
25919a91a04aSGustavo F. Padovan 	return err;
25929a91a04aSGustavo F. Padovan }
25936b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
25949a91a04aSGustavo F. Padovan 
2595d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2596d2a7ac5dSMat Martineau {
2597bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2598bed68bdeSMat Martineau 	u16 seq;
2599bed68bdeSMat Martineau 
2600b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2601bed68bdeSMat Martineau 
2602bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2603bed68bdeSMat Martineau 	control.sframe = 1;
2604bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2605bed68bdeSMat Martineau 
2606bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2607bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2608bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2609bed68bdeSMat Martineau 			control.reqseq = seq;
2610bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2611bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2612bed68bdeSMat Martineau 		}
2613bed68bdeSMat Martineau 	}
2614bed68bdeSMat Martineau 
2615bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2616d2a7ac5dSMat Martineau }
2617d2a7ac5dSMat Martineau 
2618d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2619d2a7ac5dSMat Martineau {
2620bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2621bed68bdeSMat Martineau 
2622bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2623bed68bdeSMat Martineau 
2624bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2625bed68bdeSMat Martineau 		return;
2626bed68bdeSMat Martineau 
2627bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2628bed68bdeSMat Martineau 	control.sframe = 1;
2629bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2630bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2631bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2632d2a7ac5dSMat Martineau }
2633d2a7ac5dSMat Martineau 
2634d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2635d2a7ac5dSMat Martineau {
2636bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2637bed68bdeSMat Martineau 	u16 initial_head;
2638bed68bdeSMat Martineau 	u16 seq;
2639bed68bdeSMat Martineau 
2640b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2641bed68bdeSMat Martineau 
2642bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2643bed68bdeSMat Martineau 	control.sframe = 1;
2644bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2645bed68bdeSMat Martineau 
2646bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2647bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2648bed68bdeSMat Martineau 
2649bed68bdeSMat Martineau 	do {
2650bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2651bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2652bed68bdeSMat Martineau 			break;
2653bed68bdeSMat Martineau 
2654bed68bdeSMat Martineau 		control.reqseq = seq;
2655bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2656bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2657bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2658d2a7ac5dSMat Martineau }
2659d2a7ac5dSMat Martineau 
2660608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2661608bcc6dSMat Martineau {
2662608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2663608bcc6dSMat Martineau 	u16 ackseq;
2664608bcc6dSMat Martineau 
2665b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2666608bcc6dSMat Martineau 
2667608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2668608bcc6dSMat Martineau 		return;
2669608bcc6dSMat Martineau 
2670b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2671608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2672608bcc6dSMat Martineau 
2673608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2674608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2675608bcc6dSMat Martineau 
2676608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2677608bcc6dSMat Martineau 		if (acked_skb) {
2678608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2679608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2680608bcc6dSMat Martineau 			chan->unacked_frames--;
2681608bcc6dSMat Martineau 		}
2682608bcc6dSMat Martineau 	}
2683608bcc6dSMat Martineau 
2684608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2685608bcc6dSMat Martineau 
2686608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2687608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2688608bcc6dSMat Martineau 
2689b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2690608bcc6dSMat Martineau }
2691608bcc6dSMat Martineau 
2692608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2693608bcc6dSMat Martineau {
2694608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2695608bcc6dSMat Martineau 
2696608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2697608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2698608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2699608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2700608bcc6dSMat Martineau }
2701608bcc6dSMat Martineau 
2702d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2703608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2704608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2705608bcc6dSMat Martineau {
2706608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2707608bcc6dSMat Martineau 	       event);
2708608bcc6dSMat Martineau 
2709608bcc6dSMat Martineau 	switch (event) {
2710608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2711608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2712608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2713608bcc6dSMat Martineau 
2714608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2715608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2716608bcc6dSMat Martineau 		break;
2717608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2718608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2719608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2720608bcc6dSMat Martineau 
2721608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2722608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2723608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2724608bcc6dSMat Martineau 			 */
2725608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2726608bcc6dSMat Martineau 		}
2727608bcc6dSMat Martineau 
2728608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2729608bcc6dSMat Martineau 
2730608bcc6dSMat Martineau 		break;
2731608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2732608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2733608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2734608bcc6dSMat Martineau 
2735608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2736608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2737608bcc6dSMat Martineau 
2738608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2739608bcc6dSMat Martineau 			local_control.sframe = 1;
2740608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2741608bcc6dSMat Martineau 			local_control.poll = 1;
2742608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2743a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2744608bcc6dSMat Martineau 
2745608bcc6dSMat Martineau 			chan->retry_count = 1;
2746608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2747608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2748608bcc6dSMat Martineau 		}
2749608bcc6dSMat Martineau 		break;
2750608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2751608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2752608bcc6dSMat Martineau 		break;
2753608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2754608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2755608bcc6dSMat Martineau 		chan->retry_count = 1;
2756608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2757608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2758608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2759608bcc6dSMat Martineau 		break;
2760608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2761608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2762608bcc6dSMat Martineau 		chan->retry_count = 1;
2763608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2764608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2765608bcc6dSMat Martineau 		break;
2766608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2767608bcc6dSMat Martineau 		/* Nothing to process */
2768608bcc6dSMat Martineau 		break;
2769608bcc6dSMat Martineau 	default:
2770608bcc6dSMat Martineau 		break;
2771608bcc6dSMat Martineau 	}
2772608bcc6dSMat Martineau }
2773608bcc6dSMat Martineau 
2774d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2775608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2776608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2777608bcc6dSMat Martineau {
2778608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2779608bcc6dSMat Martineau 	       event);
2780608bcc6dSMat Martineau 
2781608bcc6dSMat Martineau 	switch (event) {
2782608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2783608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2784608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2785608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2786608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2787608bcc6dSMat Martineau 		break;
2788608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2789608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2790608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2791608bcc6dSMat Martineau 
2792608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2793608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2794608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2795608bcc6dSMat Martineau 			 */
2796608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2797608bcc6dSMat Martineau 		}
2798608bcc6dSMat Martineau 
2799608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2800608bcc6dSMat Martineau 
2801608bcc6dSMat Martineau 		break;
2802608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2803608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2804608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2805608bcc6dSMat Martineau 
2806608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2807608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2808608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2809608bcc6dSMat Martineau 			local_control.sframe = 1;
2810608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2811608bcc6dSMat Martineau 			local_control.poll = 1;
2812608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2813a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2814608bcc6dSMat Martineau 
2815608bcc6dSMat Martineau 			chan->retry_count = 1;
2816608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2817608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2818608bcc6dSMat Martineau 		}
2819608bcc6dSMat Martineau 		break;
2820608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2821608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2822608bcc6dSMat Martineau 
2823608bcc6dSMat Martineau 		/* Fall through */
2824608bcc6dSMat Martineau 
2825608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2826608bcc6dSMat Martineau 		if (control && control->final) {
2827608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2828608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2829608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2830608bcc6dSMat Martineau 			chan->retry_count = 0;
2831608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2832608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2833608bcc6dSMat Martineau 		}
2834608bcc6dSMat Martineau 		break;
2835608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2836608bcc6dSMat Martineau 		/* Ignore */
2837608bcc6dSMat Martineau 		break;
2838608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2839608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2840608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2841608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2842608bcc6dSMat Martineau 			chan->retry_count++;
2843608bcc6dSMat Martineau 		} else {
28445e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
2845608bcc6dSMat Martineau 		}
2846608bcc6dSMat Martineau 		break;
2847608bcc6dSMat Martineau 	default:
2848608bcc6dSMat Martineau 		break;
2849608bcc6dSMat Martineau 	}
2850608bcc6dSMat Martineau }
2851608bcc6dSMat Martineau 
2852d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2853608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2854608bcc6dSMat Martineau {
2855608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2856608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2857608bcc6dSMat Martineau 
2858608bcc6dSMat Martineau 	switch (chan->tx_state) {
2859608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2860d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2861608bcc6dSMat Martineau 		break;
2862608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2863d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2864608bcc6dSMat Martineau 		break;
2865608bcc6dSMat Martineau 	default:
2866608bcc6dSMat Martineau 		/* Ignore event */
2867608bcc6dSMat Martineau 		break;
2868608bcc6dSMat Martineau 	}
2869608bcc6dSMat Martineau }
2870608bcc6dSMat Martineau 
28714b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
28724b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
28734b51dae9SMat Martineau {
28744b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2875401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
28764b51dae9SMat Martineau }
28774b51dae9SMat Martineau 
2878f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2879f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2880f80842a8SMat Martineau {
2881f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2882401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2883f80842a8SMat Martineau }
2884f80842a8SMat Martineau 
28850a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
28860a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
28870a708f8fSGustavo F. Padovan {
28880a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
288948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
28900a708f8fSGustavo F. Padovan 
28910a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
28920a708f8fSGustavo F. Padovan 
28933df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
28943d57dc68SGustavo F. Padovan 
28953df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
2896715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
28970a708f8fSGustavo F. Padovan 			continue;
28980a708f8fSGustavo F. Padovan 
28997f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
2900a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
29010a708f8fSGustavo F. Padovan 			continue;
29027f5396a7SGustavo Padovan 
29038bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
29040a708f8fSGustavo F. Padovan 		if (!nskb)
29050a708f8fSGustavo F. Padovan 			continue;
290680b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
29070a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
29080a708f8fSGustavo F. Padovan 	}
29093d57dc68SGustavo F. Padovan 
29103df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
29110a708f8fSGustavo F. Padovan }
29120a708f8fSGustavo F. Padovan 
29130a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
2914b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2915b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
29160a708f8fSGustavo F. Padovan {
29170a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
29180a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
29190a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
29200a708f8fSGustavo F. Padovan 	int len, count;
29210a708f8fSGustavo F. Padovan 
2922b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29230a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
29240a708f8fSGustavo F. Padovan 
2925300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2926300b962eSAnderson Lizardo 		return NULL;
2927300b962eSAnderson Lizardo 
29280a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29290a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
29300a708f8fSGustavo F. Padovan 
29318bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
29320a708f8fSGustavo F. Padovan 	if (!skb)
29330a708f8fSGustavo F. Padovan 		return NULL;
29340a708f8fSGustavo F. Padovan 
29354df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
29360a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29373300d9a9SClaudio Takahasi 
29383300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
2939dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29403300d9a9SClaudio Takahasi 	else
2941dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
29420a708f8fSGustavo F. Padovan 
29434df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
29440a708f8fSGustavo F. Padovan 	cmd->code  = code;
29450a708f8fSGustavo F. Padovan 	cmd->ident = ident;
29460a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
29470a708f8fSGustavo F. Padovan 
29480a708f8fSGustavo F. Padovan 	if (dlen) {
29490a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
295059ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
29510a708f8fSGustavo F. Padovan 		data += count;
29520a708f8fSGustavo F. Padovan 	}
29530a708f8fSGustavo F. Padovan 
29540a708f8fSGustavo F. Padovan 	len -= skb->len;
29550a708f8fSGustavo F. Padovan 
29560a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
29570a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
29580a708f8fSGustavo F. Padovan 	while (len) {
29590a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
29600a708f8fSGustavo F. Padovan 
29618bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
29620a708f8fSGustavo F. Padovan 		if (!*frag)
29630a708f8fSGustavo F. Padovan 			goto fail;
29640a708f8fSGustavo F. Padovan 
296559ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
29660a708f8fSGustavo F. Padovan 
29670a708f8fSGustavo F. Padovan 		len  -= count;
29680a708f8fSGustavo F. Padovan 		data += count;
29690a708f8fSGustavo F. Padovan 
29700a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
29710a708f8fSGustavo F. Padovan 	}
29720a708f8fSGustavo F. Padovan 
29730a708f8fSGustavo F. Padovan 	return skb;
29740a708f8fSGustavo F. Padovan 
29750a708f8fSGustavo F. Padovan fail:
29760a708f8fSGustavo F. Padovan 	kfree_skb(skb);
29770a708f8fSGustavo F. Padovan 	return NULL;
29780a708f8fSGustavo F. Padovan }
29790a708f8fSGustavo F. Padovan 
29802d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
29812d792818SGustavo Padovan 				     unsigned long *val)
29820a708f8fSGustavo F. Padovan {
29830a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
29840a708f8fSGustavo F. Padovan 	int len;
29850a708f8fSGustavo F. Padovan 
29860a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
29870a708f8fSGustavo F. Padovan 	*ptr += len;
29880a708f8fSGustavo F. Padovan 
29890a708f8fSGustavo F. Padovan 	*type = opt->type;
29900a708f8fSGustavo F. Padovan 	*olen = opt->len;
29910a708f8fSGustavo F. Padovan 
29920a708f8fSGustavo F. Padovan 	switch (opt->len) {
29930a708f8fSGustavo F. Padovan 	case 1:
29940a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
29950a708f8fSGustavo F. Padovan 		break;
29960a708f8fSGustavo F. Padovan 
29970a708f8fSGustavo F. Padovan 	case 2:
29980a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
29990a708f8fSGustavo F. Padovan 		break;
30000a708f8fSGustavo F. Padovan 
30010a708f8fSGustavo F. Padovan 	case 4:
30020a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
30030a708f8fSGustavo F. Padovan 		break;
30040a708f8fSGustavo F. Padovan 
30050a708f8fSGustavo F. Padovan 	default:
30060a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
30070a708f8fSGustavo F. Padovan 		break;
30080a708f8fSGustavo F. Padovan 	}
30090a708f8fSGustavo F. Padovan 
3010b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30110a708f8fSGustavo F. Padovan 	return len;
30120a708f8fSGustavo F. Padovan }
30130a708f8fSGustavo F. Padovan 
3014e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
30150a708f8fSGustavo F. Padovan {
30160a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
30170a708f8fSGustavo F. Padovan 
3018b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30190a708f8fSGustavo F. Padovan 
3020e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3021e860d2c9SBen Seri 		return;
3022e860d2c9SBen Seri 
30230a708f8fSGustavo F. Padovan 	opt->type = type;
30240a708f8fSGustavo F. Padovan 	opt->len  = len;
30250a708f8fSGustavo F. Padovan 
30260a708f8fSGustavo F. Padovan 	switch (len) {
30270a708f8fSGustavo F. Padovan 	case 1:
30280a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
30290a708f8fSGustavo F. Padovan 		break;
30300a708f8fSGustavo F. Padovan 
30310a708f8fSGustavo F. Padovan 	case 2:
30320a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
30330a708f8fSGustavo F. Padovan 		break;
30340a708f8fSGustavo F. Padovan 
30350a708f8fSGustavo F. Padovan 	case 4:
30360a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
30370a708f8fSGustavo F. Padovan 		break;
30380a708f8fSGustavo F. Padovan 
30390a708f8fSGustavo F. Padovan 	default:
30400a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
30410a708f8fSGustavo F. Padovan 		break;
30420a708f8fSGustavo F. Padovan 	}
30430a708f8fSGustavo F. Padovan 
30440a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
30450a708f8fSGustavo F. Padovan }
30460a708f8fSGustavo F. Padovan 
3047e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3048f89cef09SAndrei Emeltchenko {
3049f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3050f89cef09SAndrei Emeltchenko 
3051f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3052f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3053f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3054f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3055f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3056f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3057dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3058dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3059f89cef09SAndrei Emeltchenko 		break;
3060f89cef09SAndrei Emeltchenko 
3061f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3062f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3063f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3064f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3065f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3066f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3067f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3068f89cef09SAndrei Emeltchenko 		break;
3069f89cef09SAndrei Emeltchenko 
3070f89cef09SAndrei Emeltchenko 	default:
3071f89cef09SAndrei Emeltchenko 		return;
3072f89cef09SAndrei Emeltchenko 	}
3073f89cef09SAndrei Emeltchenko 
3074f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3075e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3076f89cef09SAndrei Emeltchenko }
3077f89cef09SAndrei Emeltchenko 
3078721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
30790a708f8fSGustavo F. Padovan {
3080721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3081721c4181SGustavo F. Padovan 					       ack_timer.work);
30820362520bSMat Martineau 	u16 frames_to_ack;
30830a708f8fSGustavo F. Padovan 
30842fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
30852fb9b3d4SGustavo F. Padovan 
30866be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
30876be36555SAndrei Emeltchenko 
30880362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
30890362520bSMat Martineau 				     chan->last_acked_seq);
30900362520bSMat Martineau 
30910362520bSMat Martineau 	if (frames_to_ack)
30920362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
30936be36555SAndrei Emeltchenko 
30946be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
309509bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
30960a708f8fSGustavo F. Padovan }
30970a708f8fSGustavo F. Padovan 
3098466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
30990a708f8fSGustavo F. Padovan {
31003c588192SMat Martineau 	int err;
31013c588192SMat Martineau 
3102105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3103105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
310442e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
31056a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
310642e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
31076a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3108105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3109105bdf9eSMat Martineau 	chan->sdu = NULL;
3110105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3111105bdf9eSMat Martineau 	chan->sdu_len = 0;
3112105bdf9eSMat Martineau 
3113d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3114d34c34fbSMat Martineau 
31156ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
31166ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
311708333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
311808333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
311908333283SMat Martineau 
3120105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3121105bdf9eSMat Martineau 		return 0;
3122105bdf9eSMat Martineau 
3123105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3124105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
31250a708f8fSGustavo F. Padovan 
3126721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3127721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3128721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
31290a708f8fSGustavo F. Padovan 
3130f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
31310a708f8fSGustavo F. Padovan 
31323c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31333c588192SMat Martineau 	if (err < 0)
31343c588192SMat Martineau 		return err;
31353c588192SMat Martineau 
31369dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31379dc9affcSMat Martineau 	if (err < 0)
31389dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
31399dc9affcSMat Martineau 
31409dc9affcSMat Martineau 	return err;
31410a708f8fSGustavo F. Padovan }
31420a708f8fSGustavo F. Padovan 
31430a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31440a708f8fSGustavo F. Padovan {
31450a708f8fSGustavo F. Padovan 	switch (mode) {
31460a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
31470a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
31480a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
31490a708f8fSGustavo F. Padovan 			return mode;
31500a708f8fSGustavo F. Padovan 		/* fall through */
31510a708f8fSGustavo F. Padovan 	default:
31520a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
31530a708f8fSGustavo F. Padovan 	}
31540a708f8fSGustavo F. Padovan }
31550a708f8fSGustavo F. Padovan 
3156848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31576327eb98SAndrei Emeltchenko {
31580bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
31590bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
31606327eb98SAndrei Emeltchenko }
31616327eb98SAndrei Emeltchenko 
3162848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3163f89cef09SAndrei Emeltchenko {
31640bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
31650bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3166f89cef09SAndrei Emeltchenko }
3167f89cef09SAndrei Emeltchenko 
316836c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
316936c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
317036c86c85SMat Martineau {
31716ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
317236c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
317336c86c85SMat Martineau 
317436c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
317536c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
317636c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
317736c86c85SMat Martineau 		 * controllers is 10 seconds.
317836c86c85SMat Martineau 		 *
317936c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
318036c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
318136c86c85SMat Martineau 		 * will result in a timeout that meets the above
318236c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
318336c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
318436c86c85SMat Martineau 		 */
318536c86c85SMat Martineau 
318636c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
318736c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
318836c86c85SMat Martineau 
318936c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
319036c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
319136c86c85SMat Martineau 		 * controller.
319236c86c85SMat Martineau 		 */
319336c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
319436c86c85SMat Martineau 
319536c86c85SMat Martineau 		if (ertm_to > 0xffff)
319636c86c85SMat Martineau 			ertm_to = 0xffff;
319736c86c85SMat Martineau 
319836c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
319936c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
320036c86c85SMat Martineau 	} else {
3201dcf4adbfSJoe Perches 		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3202dcf4adbfSJoe Perches 		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
320336c86c85SMat Martineau 	}
320436c86c85SMat Martineau }
320536c86c85SMat Martineau 
32066327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
32076327eb98SAndrei Emeltchenko {
32086327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3209848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
32106327eb98SAndrei Emeltchenko 		/* use extended control field */
32116327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3212836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3213836be934SAndrei Emeltchenko 	} else {
32146327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
32156327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3216836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3217836be934SAndrei Emeltchenko 	}
3218c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
32196327eb98SAndrei Emeltchenko }
32206327eb98SAndrei Emeltchenko 
3221e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
32220a708f8fSGustavo F. Padovan {
32230a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
32240c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32250a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3226e860d2c9SBen Seri 	void *endptr = data + data_size;
3227c8f79162SAndrei Emeltchenko 	u16 size;
32280a708f8fSGustavo F. Padovan 
322949208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
32300a708f8fSGustavo F. Padovan 
323173ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
32320a708f8fSGustavo F. Padovan 		goto done;
32330a708f8fSGustavo F. Padovan 
32340c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32350a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
32360a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3237c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32380a708f8fSGustavo F. Padovan 			break;
32390a708f8fSGustavo F. Padovan 
3240848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3241f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3242f89cef09SAndrei Emeltchenko 
32430a708f8fSGustavo F. Padovan 		/* fall through */
32440a708f8fSGustavo F. Padovan 	default:
32458c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32460a708f8fSGustavo F. Padovan 		break;
32470a708f8fSGustavo F. Padovan 	}
32480a708f8fSGustavo F. Padovan 
32490a708f8fSGustavo F. Padovan done:
32500c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
3251e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
32520a708f8fSGustavo F. Padovan 
32530c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32540a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
32556fea7ad1SMarcel Holtmann 		if (disable_ertm)
32566fea7ad1SMarcel Holtmann 			break;
32576fea7ad1SMarcel Holtmann 
32588c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32598c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32600a708f8fSGustavo F. Padovan 			break;
32610a708f8fSGustavo F. Padovan 
32620a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
32630a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
32640a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
32650a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
32660a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
32670a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
32680a708f8fSGustavo F. Padovan 
32690a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3270e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
32710a708f8fSGustavo F. Padovan 		break;
32720a708f8fSGustavo F. Padovan 
32730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
32740a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
327547d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
327636c86c85SMat Martineau 
327736c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3278c8f79162SAndrei Emeltchenko 
3279c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
32802d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3281c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3282c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
32830a708f8fSGustavo F. Padovan 
32846327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
32856327eb98SAndrei Emeltchenko 
32866327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
32876327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
32880a708f8fSGustavo F. Padovan 
32890a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3290e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
32910a708f8fSGustavo F. Padovan 
3292f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3293e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3294f89cef09SAndrei Emeltchenko 
32956327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
32966327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3297e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
329860918918SAndrei Emeltchenko 
329960918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
330060918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3301f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
330260918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
330360918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3304e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
330560918918SAndrei Emeltchenko 			}
33060a708f8fSGustavo F. Padovan 		break;
33070a708f8fSGustavo F. Padovan 
33080a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3309273759e2SMat Martineau 		l2cap_txwin_setup(chan);
33100a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
33110a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
33120a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
33130a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
33140a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3315c8f79162SAndrei Emeltchenko 
3316c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33172d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3318c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3319c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
33200a708f8fSGustavo F. Padovan 
33210a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3322e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
33230a708f8fSGustavo F. Padovan 
3324f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3325e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3326f89cef09SAndrei Emeltchenko 
332760918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
332847d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3329f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
333047d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
333160918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3332e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
33330a708f8fSGustavo F. Padovan 			}
33340a708f8fSGustavo F. Padovan 		break;
33350a708f8fSGustavo F. Padovan 	}
33360a708f8fSGustavo F. Padovan 
3337fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3338dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
33390a708f8fSGustavo F. Padovan 
33400a708f8fSGustavo F. Padovan 	return ptr - data;
33410a708f8fSGustavo F. Padovan }
33420a708f8fSGustavo F. Padovan 
3343e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33440a708f8fSGustavo F. Padovan {
33450a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
33460a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3347e860d2c9SBen Seri 	void *endptr = data + data_size;
334873ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
334973ffa904SGustavo F. Padovan 	int len = chan->conf_len;
33500a708f8fSGustavo F. Padovan 	int type, hint, olen;
33510a708f8fSGustavo F. Padovan 	unsigned long val;
33520a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
335342dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
335442dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
33550a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
33560a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3357c8f79162SAndrei Emeltchenko 	u16 size;
33580a708f8fSGustavo F. Padovan 
335973ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
33600a708f8fSGustavo F. Padovan 
33610a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33620a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33637c9cbd0bSMarcel Holtmann 		if (len < 0)
33647c9cbd0bSMarcel Holtmann 			break;
33650a708f8fSGustavo F. Padovan 
33660a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
33670a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
33680a708f8fSGustavo F. Padovan 
33690a708f8fSGustavo F. Padovan 		switch (type) {
33700a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3371af3d5d1cSMarcel Holtmann 			if (olen != 2)
3372af3d5d1cSMarcel Holtmann 				break;
33730a708f8fSGustavo F. Padovan 			mtu = val;
33740a708f8fSGustavo F. Padovan 			break;
33750a708f8fSGustavo F. Padovan 
33760a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3377af3d5d1cSMarcel Holtmann 			if (olen != 2)
3378af3d5d1cSMarcel Holtmann 				break;
33790c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
33800a708f8fSGustavo F. Padovan 			break;
33810a708f8fSGustavo F. Padovan 
33820a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
33830a708f8fSGustavo F. Padovan 			break;
33840a708f8fSGustavo F. Padovan 
33850a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3386af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3387af3d5d1cSMarcel Holtmann 				break;
33880a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
33890a708f8fSGustavo F. Padovan 			break;
33900a708f8fSGustavo F. Padovan 
33910a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3392af3d5d1cSMarcel Holtmann 			if (olen != 1)
3393af3d5d1cSMarcel Holtmann 				break;
33940a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3395f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
339642dceae2SAndrei Emeltchenko 			break;
33970a708f8fSGustavo F. Padovan 
339842dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3399af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3400af3d5d1cSMarcel Holtmann 				break;
340142dceae2SAndrei Emeltchenko 			remote_efs = 1;
340242dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
34030a708f8fSGustavo F. Padovan 			break;
34040a708f8fSGustavo F. Padovan 
34056327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3406af3d5d1cSMarcel Holtmann 			if (olen != 2)
3407af3d5d1cSMarcel Holtmann 				break;
34080bd49fc7SJohan Hedberg 			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
34096327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
34106327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
34116327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3412836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
34136327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
34140a708f8fSGustavo F. Padovan 			break;
34150a708f8fSGustavo F. Padovan 
34160a708f8fSGustavo F. Padovan 		default:
34170a708f8fSGustavo F. Padovan 			if (hint)
34180a708f8fSGustavo F. Padovan 				break;
34190a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
34200a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
34210a708f8fSGustavo F. Padovan 			break;
34220a708f8fSGustavo F. Padovan 		}
34230a708f8fSGustavo F. Padovan 	}
34240a708f8fSGustavo F. Padovan 
342573ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
34260a708f8fSGustavo F. Padovan 		goto done;
34270a708f8fSGustavo F. Padovan 
34280c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34290a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34300a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3431c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
34320c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
34338c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
34340a708f8fSGustavo F. Padovan 			break;
34350a708f8fSGustavo F. Padovan 		}
34360a708f8fSGustavo F. Padovan 
343742dceae2SAndrei Emeltchenko 		if (remote_efs) {
3438848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
343942dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
344042dceae2SAndrei Emeltchenko 			else
344142dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
344242dceae2SAndrei Emeltchenko 		}
344342dceae2SAndrei Emeltchenko 
34440c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
34450a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34460a708f8fSGustavo F. Padovan 
34470a708f8fSGustavo F. Padovan 		break;
34480a708f8fSGustavo F. Padovan 	}
34490a708f8fSGustavo F. Padovan 
34500a708f8fSGustavo F. Padovan done:
34510c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
34520a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
34530c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
34540a708f8fSGustavo F. Padovan 
345573ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
34560a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34570a708f8fSGustavo F. Padovan 
34582d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3459e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34600a708f8fSGustavo F. Padovan 	}
34610a708f8fSGustavo F. Padovan 
34620a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
34630a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
34640a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
34650a708f8fSGustavo F. Padovan 
34660a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
34670a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
34680a708f8fSGustavo F. Padovan 		else {
34690c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3470c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
34710a708f8fSGustavo F. Padovan 		}
3472e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34730a708f8fSGustavo F. Padovan 
347442dceae2SAndrei Emeltchenko 		if (remote_efs) {
347542dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
347642dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
347742dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
347842dceae2SAndrei Emeltchenko 
347942dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
348042dceae2SAndrei Emeltchenko 
348142dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
348242dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
348342dceae2SAndrei Emeltchenko 
348442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
348542dceae2SAndrei Emeltchenko 						   sizeof(efs),
3486e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
34870e8b207eSAndrei Emeltchenko 			} else {
34883e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
34890e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
34900e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
349142dceae2SAndrei Emeltchenko 			}
349242dceae2SAndrei Emeltchenko 		}
349342dceae2SAndrei Emeltchenko 
34940a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
34950a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
349647d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3497c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
34980a708f8fSGustavo F. Padovan 			break;
34990a708f8fSGustavo F. Padovan 
35000a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
35016327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
35022c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
35036327eb98SAndrei Emeltchenko 			else
35046327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
35056327eb98SAndrei Emeltchenko 
35062c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
35070a708f8fSGustavo F. Padovan 
3508c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35092d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35102d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3511c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3512c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35130a708f8fSGustavo F. Padovan 
351436c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
35150a708f8fSGustavo F. Padovan 
3516c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35170a708f8fSGustavo F. Padovan 
35180a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3519e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35200a708f8fSGustavo F. Padovan 
352142dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
352242dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
352342dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
352442dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
352542dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
352642dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
352742dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
352842dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
352942dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
353042dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
353142dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35322d792818SGustavo Padovan 						   sizeof(efs),
3533e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
353442dceae2SAndrei Emeltchenko 			}
35350a708f8fSGustavo F. Padovan 			break;
35360a708f8fSGustavo F. Padovan 
35370a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3538c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35392d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35402d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3541c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3542c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35430a708f8fSGustavo F. Padovan 
3544c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35450a708f8fSGustavo F. Padovan 
35462d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3547e860d2c9SBen Seri 					   (unsigned long) &rfc, endptr - ptr);
35480a708f8fSGustavo F. Padovan 
35490a708f8fSGustavo F. Padovan 			break;
35500a708f8fSGustavo F. Padovan 
35510a708f8fSGustavo F. Padovan 		default:
35520a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
35530a708f8fSGustavo F. Padovan 
35540a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
35550c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
35560a708f8fSGustavo F. Padovan 		}
35570a708f8fSGustavo F. Padovan 
35580a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3559c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35600a708f8fSGustavo F. Padovan 	}
3561fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
35620a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
3563dcf4adbfSJoe Perches 	rsp->flags  = cpu_to_le16(0);
35640a708f8fSGustavo F. Padovan 
35650a708f8fSGustavo F. Padovan 	return ptr - data;
35660a708f8fSGustavo F. Padovan }
35670a708f8fSGustavo F. Padovan 
35682d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3569e860d2c9SBen Seri 				void *data, size_t size, u16 *result)
35700a708f8fSGustavo F. Padovan {
35710a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
35720a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3573e860d2c9SBen Seri 	void *endptr = data + size;
35740a708f8fSGustavo F. Padovan 	int type, olen;
35750a708f8fSGustavo F. Padovan 	unsigned long val;
357636e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
357766af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
35780a708f8fSGustavo F. Padovan 
3579fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
35800a708f8fSGustavo F. Padovan 
35810a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35820a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
35837c9cbd0bSMarcel Holtmann 		if (len < 0)
35847c9cbd0bSMarcel Holtmann 			break;
35850a708f8fSGustavo F. Padovan 
35860a708f8fSGustavo F. Padovan 		switch (type) {
35870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3588af3d5d1cSMarcel Holtmann 			if (olen != 2)
3589af3d5d1cSMarcel Holtmann 				break;
35900a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
35910a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
35920c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
35930a708f8fSGustavo F. Padovan 			} else
35940c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
3595af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3596af3d5d1cSMarcel Holtmann 					   endptr - ptr);
35970a708f8fSGustavo F. Padovan 			break;
35980a708f8fSGustavo F. Padovan 
35990a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3600af3d5d1cSMarcel Holtmann 			if (olen != 2)
3601af3d5d1cSMarcel Holtmann 				break;
36020c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
3603af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3604af3d5d1cSMarcel Holtmann 					   chan->flush_to, endptr - ptr);
36050a708f8fSGustavo F. Padovan 			break;
36060a708f8fSGustavo F. Padovan 
36070a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3608af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3609af3d5d1cSMarcel Holtmann 				break;
36100a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3611c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
36120c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
36130a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
361447d1ec61SGustavo F. Padovan 			chan->fcs = 0;
3615af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3616af3d5d1cSMarcel Holtmann 					   (unsigned long) &rfc, endptr - ptr);
36170a708f8fSGustavo F. Padovan 			break;
36186327eb98SAndrei Emeltchenko 
36196327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3620af3d5d1cSMarcel Holtmann 			if (olen != 2)
3621af3d5d1cSMarcel Holtmann 				break;
3622c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
36233e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3624e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
36256327eb98SAndrei Emeltchenko 			break;
362666af7aafSAndrei Emeltchenko 
362766af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3628af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3629af3d5d1cSMarcel Holtmann 				break;
363066af7aafSAndrei Emeltchenko 			memcpy(&efs, (void *)val, olen);
363166af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
363266af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
363366af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
363466af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
36352d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3636e860d2c9SBen Seri 					   (unsigned long) &efs, endptr - ptr);
363766af7aafSAndrei Emeltchenko 			break;
3638cbabee78SAndrei Emeltchenko 
3639cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3640af3d5d1cSMarcel Holtmann 			if (olen != 1)
3641af3d5d1cSMarcel Holtmann 				break;
3642cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3643cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3644f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3645cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3646cbabee78SAndrei Emeltchenko 			break;
36470a708f8fSGustavo F. Padovan 		}
36480a708f8fSGustavo F. Padovan 	}
36490a708f8fSGustavo F. Padovan 
36500c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36510a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
36520a708f8fSGustavo F. Padovan 
36530c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
36540a708f8fSGustavo F. Padovan 
36550e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36560a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36570a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
365847d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
365947d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
366047d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3661c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3662c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3663c20f8e35SMat Martineau 						      rfc.txwin_size);
366466af7aafSAndrei Emeltchenko 
366566af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
366666af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
366766af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
366866af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
366966af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
367066af7aafSAndrei Emeltchenko 				chan->local_flush_to =
367166af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
367266af7aafSAndrei Emeltchenko 			}
36730a708f8fSGustavo F. Padovan 			break;
367466af7aafSAndrei Emeltchenko 
36750a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
367647d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
36770a708f8fSGustavo F. Padovan 		}
36780a708f8fSGustavo F. Padovan 	}
36790a708f8fSGustavo F. Padovan 
3680fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
3681dcf4adbfSJoe Perches 	req->flags  = cpu_to_le16(0);
36820a708f8fSGustavo F. Padovan 
36830a708f8fSGustavo F. Padovan 	return ptr - data;
36840a708f8fSGustavo F. Padovan }
36850a708f8fSGustavo F. Padovan 
36862d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
36872d792818SGustavo Padovan 				u16 result, u16 flags)
36880a708f8fSGustavo F. Padovan {
36890a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
36900a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
36910a708f8fSGustavo F. Padovan 
3692fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
36930a708f8fSGustavo F. Padovan 
3694fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
36950a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
36960a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
36970a708f8fSGustavo F. Padovan 
36980a708f8fSGustavo F. Padovan 	return ptr - data;
36990a708f8fSGustavo F. Padovan }
37000a708f8fSGustavo F. Padovan 
370127e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
370227e2d4c8SJohan Hedberg {
370327e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
370427e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
370527e2d4c8SJohan Hedberg 
370627e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
370727e2d4c8SJohan Hedberg 
370827e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
370927e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
37103916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
37110cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
3712571f7390SMallikarjun Phulari 	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
371327e2d4c8SJohan Hedberg 
371427e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
371527e2d4c8SJohan Hedberg 		       &rsp);
371627e2d4c8SJohan Hedberg }
371727e2d4c8SJohan Hedberg 
37188c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3719710f9b0aSGustavo F. Padovan {
3720710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
37218c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3722710f9b0aSGustavo F. Padovan 	u8 buf[128];
3723439f34acSAndrei Emeltchenko 	u8 rsp_code;
3724710f9b0aSGustavo F. Padovan 
3725fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3726fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3727dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3728dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3729439f34acSAndrei Emeltchenko 
3730439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3731439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3732439f34acSAndrei Emeltchenko 	else
3733439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3734439f34acSAndrei Emeltchenko 
3735439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3736439f34acSAndrei Emeltchenko 
3737439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3738710f9b0aSGustavo F. Padovan 
3739c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3740710f9b0aSGustavo F. Padovan 		return;
3741710f9b0aSGustavo F. Padovan 
3742710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3743e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
3744710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3745710f9b0aSGustavo F. Padovan }
3746710f9b0aSGustavo F. Padovan 
374747d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
37480a708f8fSGustavo F. Padovan {
37490a708f8fSGustavo F. Padovan 	int type, olen;
37500a708f8fSGustavo F. Padovan 	unsigned long val;
3751c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3752c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3753c20f8e35SMat Martineau 	 */
3754c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3755c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3756c20f8e35SMat Martineau 		.mode = chan->mode,
3757dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3758dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3759c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3760c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3761c20f8e35SMat Martineau 	};
37620a708f8fSGustavo F. Padovan 
376347d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
37640a708f8fSGustavo F. Padovan 
37650c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
37660a708f8fSGustavo F. Padovan 		return;
37670a708f8fSGustavo F. Padovan 
37680a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37690a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37707c9cbd0bSMarcel Holtmann 		if (len < 0)
37717c9cbd0bSMarcel Holtmann 			break;
37720a708f8fSGustavo F. Padovan 
3773c20f8e35SMat Martineau 		switch (type) {
3774c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3775af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3776af3d5d1cSMarcel Holtmann 				break;
37770a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3778c20f8e35SMat Martineau 			break;
3779c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3780af3d5d1cSMarcel Holtmann 			if (olen != 2)
3781af3d5d1cSMarcel Holtmann 				break;
3782c20f8e35SMat Martineau 			txwin_ext = val;
3783c20f8e35SMat Martineau 			break;
3784c20f8e35SMat Martineau 		}
37850a708f8fSGustavo F. Padovan 	}
37860a708f8fSGustavo F. Padovan 
37870a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
37880a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
378947d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
379047d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
379147d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3792c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3793c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3794c20f8e35SMat Martineau 		else
3795c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3796c20f8e35SMat Martineau 					      rfc.txwin_size);
37970a708f8fSGustavo F. Padovan 		break;
37980a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
379947d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38000a708f8fSGustavo F. Padovan 	}
38010a708f8fSGustavo F. Padovan }
38020a708f8fSGustavo F. Padovan 
38032d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3804cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3805cb3b3152SJohan Hedberg 				    u8 *data)
38060a708f8fSGustavo F. Padovan {
3807e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
38080a708f8fSGustavo F. Padovan 
3809cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3810cb3b3152SJohan Hedberg 		return -EPROTO;
3811cb3b3152SJohan Hedberg 
3812e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
38130a708f8fSGustavo F. Padovan 		return 0;
38140a708f8fSGustavo F. Padovan 
38150a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
38160a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
381717cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
38180a708f8fSGustavo F. Padovan 
38190a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
38200a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
38210a708f8fSGustavo F. Padovan 
38220a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
38230a708f8fSGustavo F. Padovan 	}
38240a708f8fSGustavo F. Padovan 
38250a708f8fSGustavo F. Padovan 	return 0;
38260a708f8fSGustavo F. Padovan }
38270a708f8fSGustavo F. Padovan 
38281700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
38291700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
38304c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
38310a708f8fSGustavo F. Padovan {
38320a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
38330a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
383423691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
38350a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
38360a708f8fSGustavo F. Padovan 
38370a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
38380a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
38390a708f8fSGustavo F. Padovan 
3840097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
38410a708f8fSGustavo F. Padovan 
38420a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
38436f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3844bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
384523691d75SGustavo F. Padovan 	if (!pchan) {
38460a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
38470a708f8fSGustavo F. Padovan 		goto sendresp;
38480a708f8fSGustavo F. Padovan 	}
38490a708f8fSGustavo F. Padovan 
38503df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38518ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
38520a708f8fSGustavo F. Padovan 
38530a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
3854dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
38550a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
38569f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
38570a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
38580a708f8fSGustavo F. Padovan 		goto response;
38590a708f8fSGustavo F. Padovan 	}
38600a708f8fSGustavo F. Padovan 
38610a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
38620a708f8fSGustavo F. Padovan 
3863dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
3864dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
3865dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
38662dfa1003SGustavo Padovan 		goto response;
3867dd1a8f8aSMallikarjun Phulari 	}
3868dd1a8f8aSMallikarjun Phulari 
3869dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
3870dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
3871dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
3872dd1a8f8aSMallikarjun Phulari 		goto response;
3873dd1a8f8aSMallikarjun Phulari 	}
38742dfa1003SGustavo Padovan 
387580b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
387680808e43SGustavo F. Padovan 	if (!chan)
38770a708f8fSGustavo F. Padovan 		goto response;
38780a708f8fSGustavo F. Padovan 
3879330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
3880330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
3881330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
3882330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3883330b6c15SSyam Sidhardhan 	 */
3884330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3885330b6c15SSyam Sidhardhan 
38867eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
38877eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
3888a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
3889a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
3890fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3891fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
38921700915fSMat Martineau 	chan->local_amp_id = amp_id;
38930a708f8fSGustavo F. Padovan 
38946be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
389548454079SGustavo F. Padovan 
3896fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
38970a708f8fSGustavo F. Padovan 
38988d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
38990a708f8fSGustavo F. Padovan 
3900fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
39010a708f8fSGustavo F. Padovan 
39020a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3903e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
3904bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
3905f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
39060a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
39070a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
39082dc4e510SGustavo Padovan 				chan->ops->defer(chan);
39090a708f8fSGustavo F. Padovan 			} else {
39101700915fSMat Martineau 				/* Force pending result for AMP controllers.
39111700915fSMat Martineau 				 * The connection will succeed after the
39121700915fSMat Martineau 				 * physical link is up.
39131700915fSMat Martineau 				 */
39146ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
3915f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
39160a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
39176ed971caSMarcel Holtmann 				} else {
3918f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
39196ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
39201700915fSMat Martineau 				}
39210a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
39220a708f8fSGustavo F. Padovan 			}
39230a708f8fSGustavo F. Padovan 		} else {
3924f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
39250a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
39260a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
39270a708f8fSGustavo F. Padovan 		}
39280a708f8fSGustavo F. Padovan 	} else {
3929f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
39300a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
39310a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
39320a708f8fSGustavo F. Padovan 	}
39330a708f8fSGustavo F. Padovan 
39340a708f8fSGustavo F. Padovan response:
39358ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
39363df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3937a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
39380a708f8fSGustavo F. Padovan 
39390a708f8fSGustavo F. Padovan sendresp:
39400a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
39410a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
39420a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
39430a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
39444c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
39450a708f8fSGustavo F. Padovan 
39460a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
39470a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
3948dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
39490a708f8fSGustavo F. Padovan 
39500a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
39510a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
39520a708f8fSGustavo F. Padovan 
3953ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
39540a708f8fSGustavo F. Padovan 
39552d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
39562d792818SGustavo Padovan 			       sizeof(info), &info);
39570a708f8fSGustavo F. Padovan 	}
39580a708f8fSGustavo F. Padovan 
3959c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
39600a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
39610a708f8fSGustavo F. Padovan 		u8 buf[128];
3962c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
39630a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3964e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
396573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
39660a708f8fSGustavo F. Padovan 	}
39671700915fSMat Martineau 
39681700915fSMat Martineau 	return chan;
39694c89b6aaSMat Martineau }
39700a708f8fSGustavo F. Padovan 
39714c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
3972cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
39734c89b6aaSMat Martineau {
39747b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
39757b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
39767b064edaSJaganath Kanakkassery 
3977cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
3978cb3b3152SJohan Hedberg 		return -EPROTO;
3979cb3b3152SJohan Hedberg 
39807b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
3981d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
39827b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
398348ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, hcon, 0, NULL, 0);
39847b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
39857b064edaSJaganath Kanakkassery 
3986300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
39870a708f8fSGustavo F. Padovan 	return 0;
39880a708f8fSGustavo F. Padovan }
39890a708f8fSGustavo F. Padovan 
39905909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
3991cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3992cb3b3152SJohan Hedberg 				    u8 *data)
39930a708f8fSGustavo F. Padovan {
39940a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
39950a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
399648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
39970a708f8fSGustavo F. Padovan 	u8 req[128];
39983df91ea2SAndrei Emeltchenko 	int err;
39990a708f8fSGustavo F. Padovan 
4000cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4001cb3b3152SJohan Hedberg 		return -EPROTO;
4002cb3b3152SJohan Hedberg 
40030a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
40040a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
40050a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
40060a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
40070a708f8fSGustavo F. Padovan 
40081b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
40091b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
40100a708f8fSGustavo F. Padovan 
40113df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
40123df91ea2SAndrei Emeltchenko 
40130a708f8fSGustavo F. Padovan 	if (scid) {
40143df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
40153df91ea2SAndrei Emeltchenko 		if (!chan) {
401621870b52SJohan Hedberg 			err = -EBADSLT;
40173df91ea2SAndrei Emeltchenko 			goto unlock;
40183df91ea2SAndrei Emeltchenko 		}
40190a708f8fSGustavo F. Padovan 	} else {
40203df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
40213df91ea2SAndrei Emeltchenko 		if (!chan) {
402221870b52SJohan Hedberg 			err = -EBADSLT;
40233df91ea2SAndrei Emeltchenko 			goto unlock;
40243df91ea2SAndrei Emeltchenko 		}
40250a708f8fSGustavo F. Padovan 	}
40260a708f8fSGustavo F. Padovan 
40273df91ea2SAndrei Emeltchenko 	err = 0;
40283df91ea2SAndrei Emeltchenko 
40296be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
403048454079SGustavo F. Padovan 
40310a708f8fSGustavo F. Padovan 	switch (result) {
40320a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
403389bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4034fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4035fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4036c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
40370a708f8fSGustavo F. Padovan 
4038c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
40390a708f8fSGustavo F. Padovan 			break;
40400a708f8fSGustavo F. Padovan 
40410a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4042e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
404373ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40440a708f8fSGustavo F. Padovan 		break;
40450a708f8fSGustavo F. Padovan 
40460a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4047c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
40480a708f8fSGustavo F. Padovan 		break;
40490a708f8fSGustavo F. Padovan 
40500a708f8fSGustavo F. Padovan 	default:
405148454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
40520a708f8fSGustavo F. Padovan 		break;
40530a708f8fSGustavo F. Padovan 	}
40540a708f8fSGustavo F. Padovan 
40556be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
40563df91ea2SAndrei Emeltchenko 
40573df91ea2SAndrei Emeltchenko unlock:
40583df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40593df91ea2SAndrei Emeltchenko 
40603df91ea2SAndrei Emeltchenko 	return err;
40610a708f8fSGustavo F. Padovan }
40620a708f8fSGustavo F. Padovan 
406347d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
40640a708f8fSGustavo F. Padovan {
40650a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
40660a708f8fSGustavo F. Padovan 	 * sides request it.
40670a708f8fSGustavo F. Padovan 	 */
40680c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
406947d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4070f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
407147d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
40720a708f8fSGustavo F. Padovan }
40730a708f8fSGustavo F. Padovan 
407429d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
407529d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
407629d8a590SAndrei Emeltchenko {
407729d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
407829d8a590SAndrei Emeltchenko 
407929d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
408029d8a590SAndrei Emeltchenko 	       flags);
408129d8a590SAndrei Emeltchenko 
408229d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
408329d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
408429d8a590SAndrei Emeltchenko 
408529d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
408629d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
408729d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
408829d8a590SAndrei Emeltchenko }
408929d8a590SAndrei Emeltchenko 
4090662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4091662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4092662d652dSJohan Hedberg {
4093662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4094662d652dSJohan Hedberg 
4095dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4096662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4097662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4098662d652dSJohan Hedberg 
4099662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4100662d652dSJohan Hedberg }
4101662d652dSJohan Hedberg 
41022d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
41032d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
41042d792818SGustavo Padovan 				   u8 *data)
41050a708f8fSGustavo F. Padovan {
41060a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
41070a708f8fSGustavo F. Padovan 	u16 dcid, flags;
41080a708f8fSGustavo F. Padovan 	u8 rsp[64];
410948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
41103c588192SMat Martineau 	int len, err = 0;
41110a708f8fSGustavo F. Padovan 
4112cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4113cb3b3152SJohan Hedberg 		return -EPROTO;
4114cb3b3152SJohan Hedberg 
41150a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
41160a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
41170a708f8fSGustavo F. Padovan 
41180a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
41190a708f8fSGustavo F. Padovan 
4120baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4121662d652dSJohan Hedberg 	if (!chan) {
4122662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4123662d652dSJohan Hedberg 		return 0;
4124662d652dSJohan Hedberg 	}
41250a708f8fSGustavo F. Padovan 
4126033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4127662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4128662d652dSJohan Hedberg 				       chan->dcid);
41290a708f8fSGustavo F. Padovan 		goto unlock;
41300a708f8fSGustavo F. Padovan 	}
41310a708f8fSGustavo F. Padovan 
41320a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
41330a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4134cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
41350a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4136fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41370a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
41380a708f8fSGustavo F. Padovan 		goto unlock;
41390a708f8fSGustavo F. Padovan 	}
41400a708f8fSGustavo F. Padovan 
41410a708f8fSGustavo F. Padovan 	/* Store config. */
414273ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
414373ffa904SGustavo F. Padovan 	chan->conf_len += len;
41440a708f8fSGustavo F. Padovan 
414559e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
41460a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
41470a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4148fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
41495325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
41500a708f8fSGustavo F. Padovan 		goto unlock;
41510a708f8fSGustavo F. Padovan 	}
41520a708f8fSGustavo F. Padovan 
41530a708f8fSGustavo F. Padovan 	/* Complete config. */
4154e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
41550a708f8fSGustavo F. Padovan 	if (len < 0) {
41565e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
41570a708f8fSGustavo F. Padovan 		goto unlock;
41580a708f8fSGustavo F. Padovan 	}
41590a708f8fSGustavo F. Padovan 
41601500109bSMat Martineau 	chan->ident = cmd->ident;
41610a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
416273ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
41630a708f8fSGustavo F. Padovan 
41640a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
416573ffa904SGustavo F. Padovan 	chan->conf_len = 0;
41660a708f8fSGustavo F. Padovan 
4167c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
41680a708f8fSGustavo F. Padovan 		goto unlock;
41690a708f8fSGustavo F. Padovan 
4170c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
417147d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
41720a708f8fSGustavo F. Padovan 
4173105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4174105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
41753c588192SMat Martineau 			err = l2cap_ertm_init(chan);
41760a708f8fSGustavo F. Padovan 
41773c588192SMat Martineau 		if (err < 0)
41785e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
41793c588192SMat Martineau 		else
4180cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
41813c588192SMat Martineau 
41820a708f8fSGustavo F. Padovan 		goto unlock;
41830a708f8fSGustavo F. Padovan 	}
41840a708f8fSGustavo F. Padovan 
4185c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
41860a708f8fSGustavo F. Padovan 		u8 buf[64];
41870a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4188e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
418973ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41900a708f8fSGustavo F. Padovan 	}
41910a708f8fSGustavo F. Padovan 
419249c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
41930e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
41940e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
41950e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
41960e8b207eSAndrei Emeltchenko 
41970e8b207eSAndrei Emeltchenko 		/* check compatibility */
41980e8b207eSAndrei Emeltchenko 
419979de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4200f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
420129d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
420279de886dSAndrei Emeltchenko 		else
420379de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
42040e8b207eSAndrei Emeltchenko 	}
42050e8b207eSAndrei Emeltchenko 
42060a708f8fSGustavo F. Padovan unlock:
42076be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
42083c588192SMat Martineau 	return err;
42090a708f8fSGustavo F. Padovan }
42100a708f8fSGustavo F. Padovan 
42112d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4212cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4213cb3b3152SJohan Hedberg 				   u8 *data)
42140a708f8fSGustavo F. Padovan {
42150a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
42160a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
421748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4218cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
42193c588192SMat Martineau 	int err = 0;
42200a708f8fSGustavo F. Padovan 
4221cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4222cb3b3152SJohan Hedberg 		return -EPROTO;
4223cb3b3152SJohan Hedberg 
42240a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
42250a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
42260a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
42270a708f8fSGustavo F. Padovan 
422861386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
422961386cbaSAndrei Emeltchenko 	       result, len);
42300a708f8fSGustavo F. Padovan 
4231baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
423248454079SGustavo F. Padovan 	if (!chan)
42330a708f8fSGustavo F. Padovan 		return 0;
42340a708f8fSGustavo F. Padovan 
42350a708f8fSGustavo F. Padovan 	switch (result) {
42360a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
423747d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
42380e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42390a708f8fSGustavo F. Padovan 		break;
42400a708f8fSGustavo F. Padovan 
42410e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
42420e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
42430e8b207eSAndrei Emeltchenko 
42440e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
42450e8b207eSAndrei Emeltchenko 			char buf[64];
42460e8b207eSAndrei Emeltchenko 
42470e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4248e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
42490e8b207eSAndrei Emeltchenko 			if (len < 0) {
42505e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42510e8b207eSAndrei Emeltchenko 				goto done;
42520e8b207eSAndrei Emeltchenko 			}
42530e8b207eSAndrei Emeltchenko 
4254f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
425579de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
425679de886dSAndrei Emeltchenko 							0);
42575ce66b59SAndrei Emeltchenko 			} else {
42585ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
42595ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
426079de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
42610e8b207eSAndrei Emeltchenko 				}
42625ce66b59SAndrei Emeltchenko 			}
42635ce66b59SAndrei Emeltchenko 		}
42640e8b207eSAndrei Emeltchenko 		goto done;
42650e8b207eSAndrei Emeltchenko 
42660a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
426773ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
42680a708f8fSGustavo F. Padovan 			char req[64];
42690a708f8fSGustavo F. Padovan 
42700a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
42715e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42720a708f8fSGustavo F. Padovan 				goto done;
42730a708f8fSGustavo F. Padovan 			}
42740a708f8fSGustavo F. Padovan 
42750a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
42760a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4277b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4278e860d2c9SBen Seri 						   req, sizeof(req), &result);
42790a708f8fSGustavo F. Padovan 			if (len < 0) {
42805e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
42810a708f8fSGustavo F. Padovan 				goto done;
42820a708f8fSGustavo F. Padovan 			}
42830a708f8fSGustavo F. Padovan 
42840a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
42850a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
428673ffa904SGustavo F. Padovan 			chan->num_conf_req++;
42870a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
42880a708f8fSGustavo F. Padovan 				goto done;
42890a708f8fSGustavo F. Padovan 			break;
42900a708f8fSGustavo F. Padovan 		}
42916317950cSGustavo A. R. Silva 		/* fall through */
42920a708f8fSGustavo F. Padovan 
42930a708f8fSGustavo F. Padovan 	default:
42946be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
42952e0052e4SAndrei Emeltchenko 
4296ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
42975e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42980a708f8fSGustavo F. Padovan 		goto done;
42990a708f8fSGustavo F. Padovan 	}
43000a708f8fSGustavo F. Padovan 
430159e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
43020a708f8fSGustavo F. Padovan 		goto done;
43030a708f8fSGustavo F. Padovan 
4304c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
43050a708f8fSGustavo F. Padovan 
4306c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
430747d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
43080a708f8fSGustavo F. Padovan 
4309105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4310105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
43113c588192SMat Martineau 			err = l2cap_ertm_init(chan);
43120a708f8fSGustavo F. Padovan 
43133c588192SMat Martineau 		if (err < 0)
43145e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
43153c588192SMat Martineau 		else
4316cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
43170a708f8fSGustavo F. Padovan 	}
43180a708f8fSGustavo F. Padovan 
43190a708f8fSGustavo F. Padovan done:
43206be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43213c588192SMat Martineau 	return err;
43220a708f8fSGustavo F. Padovan }
43230a708f8fSGustavo F. Padovan 
43242d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4325cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4326cb3b3152SJohan Hedberg 				       u8 *data)
43270a708f8fSGustavo F. Padovan {
43280a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
43290a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
43300a708f8fSGustavo F. Padovan 	u16 dcid, scid;
433148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43320a708f8fSGustavo F. Padovan 
4333cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4334cb3b3152SJohan Hedberg 		return -EPROTO;
4335cb3b3152SJohan Hedberg 
43360a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
43370a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
43380a708f8fSGustavo F. Padovan 
43390a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
43400a708f8fSGustavo F. Padovan 
43413df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43423df91ea2SAndrei Emeltchenko 
43433df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
43443df91ea2SAndrei Emeltchenko 	if (!chan) {
43453df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4346662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4347662d652dSJohan Hedberg 		return 0;
43483df91ea2SAndrei Emeltchenko 	}
43490a708f8fSGustavo F. Padovan 
43506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
43516be36555SAndrei Emeltchenko 
4352fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4353fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
43540a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
43550a708f8fSGustavo F. Padovan 
43565ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
43570a708f8fSGustavo F. Padovan 
435861d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
435948454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
43606be36555SAndrei Emeltchenko 
43616be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43620a708f8fSGustavo F. Padovan 
436380b98027SGustavo Padovan 	chan->ops->close(chan);
436461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
43653df91ea2SAndrei Emeltchenko 
43663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43673df91ea2SAndrei Emeltchenko 
43680a708f8fSGustavo F. Padovan 	return 0;
43690a708f8fSGustavo F. Padovan }
43700a708f8fSGustavo F. Padovan 
43712d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4372cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4373cb3b3152SJohan Hedberg 				       u8 *data)
43740a708f8fSGustavo F. Padovan {
43750a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
43760a708f8fSGustavo F. Padovan 	u16 dcid, scid;
437748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43780a708f8fSGustavo F. Padovan 
4379cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4380cb3b3152SJohan Hedberg 		return -EPROTO;
4381cb3b3152SJohan Hedberg 
43820a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
43830a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
43840a708f8fSGustavo F. Padovan 
43850a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
43860a708f8fSGustavo F. Padovan 
43873df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43883df91ea2SAndrei Emeltchenko 
43893df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
43903df91ea2SAndrei Emeltchenko 	if (!chan) {
43913df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
43920a708f8fSGustavo F. Padovan 		return 0;
43933df91ea2SAndrei Emeltchenko 	}
43940a708f8fSGustavo F. Padovan 
43956be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
439648454079SGustavo F. Padovan 
439728261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
439828261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
439928261da8SMatias Karhumaa 		mutex_unlock(&conn->chan_lock);
440028261da8SMatias Karhumaa 		return 0;
440128261da8SMatias Karhumaa 	}
440228261da8SMatias Karhumaa 
440361d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
440448454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
44056be36555SAndrei Emeltchenko 
44066be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44070a708f8fSGustavo F. Padovan 
440880b98027SGustavo Padovan 	chan->ops->close(chan);
440961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44103df91ea2SAndrei Emeltchenko 
44113df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
44123df91ea2SAndrei Emeltchenko 
44130a708f8fSGustavo F. Padovan 	return 0;
44140a708f8fSGustavo F. Padovan }
44150a708f8fSGustavo F. Padovan 
44162d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4417cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4418cb3b3152SJohan Hedberg 					u8 *data)
44190a708f8fSGustavo F. Padovan {
44200a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
44210a708f8fSGustavo F. Padovan 	u16 type;
44220a708f8fSGustavo F. Padovan 
4423cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4424cb3b3152SJohan Hedberg 		return -EPROTO;
4425cb3b3152SJohan Hedberg 
44260a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
44270a708f8fSGustavo F. Padovan 
44280a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
44290a708f8fSGustavo F. Padovan 
44300a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
44310a708f8fSGustavo F. Padovan 		u8 buf[8];
44320a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
44330a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4434dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4435dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
44360a708f8fSGustavo F. Padovan 		if (!disable_ertm)
44370a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
44380a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
44390bd49fc7SJohan Hedberg 		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
44406327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
44416327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4442a5fd6f30SAndrei Emeltchenko 
44430a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
44442d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44452d792818SGustavo Padovan 			       buf);
44460a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
44470a708f8fSGustavo F. Padovan 		u8 buf[12];
44480a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
444950a147cdSMat Martineau 
4450dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4451dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
44520bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
44530bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
44542d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
44552d792818SGustavo Padovan 			       buf);
44560a708f8fSGustavo F. Padovan 	} else {
44570a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
44580a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4459dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
44602d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
44612d792818SGustavo Padovan 			       &rsp);
44620a708f8fSGustavo F. Padovan 	}
44630a708f8fSGustavo F. Padovan 
44640a708f8fSGustavo F. Padovan 	return 0;
44650a708f8fSGustavo F. Padovan }
44660a708f8fSGustavo F. Padovan 
44672d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4468cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4469cb3b3152SJohan Hedberg 					u8 *data)
44700a708f8fSGustavo F. Padovan {
44710a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
44720a708f8fSGustavo F. Padovan 	u16 type, result;
44730a708f8fSGustavo F. Padovan 
44743f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4475cb3b3152SJohan Hedberg 		return -EPROTO;
4476cb3b3152SJohan Hedberg 
44770a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
44780a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
44790a708f8fSGustavo F. Padovan 
44800a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
44810a708f8fSGustavo F. Padovan 
4482e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4483e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4484e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4485e90165beSAndrei Emeltchenko 		return 0;
4486e90165beSAndrei Emeltchenko 
448717cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
44880a708f8fSGustavo F. Padovan 
44890a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
44900a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
44910a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
44920a708f8fSGustavo F. Padovan 
44930a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
44940a708f8fSGustavo F. Padovan 
44950a708f8fSGustavo F. Padovan 		return 0;
44960a708f8fSGustavo F. Padovan 	}
44970a708f8fSGustavo F. Padovan 
4498978c93b9SAndrei Emeltchenko 	switch (type) {
4499978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
45000a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
45010a708f8fSGustavo F. Padovan 
45020a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
45030a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4504dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
45050a708f8fSGustavo F. Padovan 
45060a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
45070a708f8fSGustavo F. Padovan 
45080a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
45090a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
45100a708f8fSGustavo F. Padovan 		} else {
45110a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45120a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
45130a708f8fSGustavo F. Padovan 
45140a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
45150a708f8fSGustavo F. Padovan 		}
4516978c93b9SAndrei Emeltchenko 		break;
4517978c93b9SAndrei Emeltchenko 
4518978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
45190bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
45200a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45210a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
45220a708f8fSGustavo F. Padovan 
45230a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4524978c93b9SAndrei Emeltchenko 		break;
45250a708f8fSGustavo F. Padovan 	}
45260a708f8fSGustavo F. Padovan 
45270a708f8fSGustavo F. Padovan 	return 0;
45280a708f8fSGustavo F. Padovan }
45290a708f8fSGustavo F. Padovan 
45301700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
45312d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
45322d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4533f94ff6ffSMat Martineau {
4534f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
45356e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
45361700915fSMat Martineau 	struct l2cap_chan *chan;
45376e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4538f94ff6ffSMat Martineau 	u16 psm, scid;
4539f94ff6ffSMat Martineau 
4540f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4541f94ff6ffSMat Martineau 		return -EPROTO;
4542f94ff6ffSMat Martineau 
45430bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4544f94ff6ffSMat Martineau 		return -EINVAL;
4545f94ff6ffSMat Martineau 
4546f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4547f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4548f94ff6ffSMat Martineau 
4549ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4550f94ff6ffSMat Martineau 
45516e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
45526ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
45536e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45546e1df6a6SAndrei Emeltchenko 			      req->amp_id);
45556e1df6a6SAndrei Emeltchenko 		return 0;
45566e1df6a6SAndrei Emeltchenko 	}
45571700915fSMat Martineau 
45581700915fSMat Martineau 	/* Validate AMP controller id */
45591700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
45606e1df6a6SAndrei Emeltchenko 	if (!hdev)
45616e1df6a6SAndrei Emeltchenko 		goto error;
45621700915fSMat Martineau 
45636e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
45646e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
45656e1df6a6SAndrei Emeltchenko 		goto error;
45666e1df6a6SAndrei Emeltchenko 	}
45676e1df6a6SAndrei Emeltchenko 
45686e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
45696e1df6a6SAndrei Emeltchenko 			     req->amp_id);
45706e1df6a6SAndrei Emeltchenko 	if (chan) {
45716e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
45726e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
45736e1df6a6SAndrei Emeltchenko 
457498e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
457598e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
45766e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
45776e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4578662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4579662d652dSJohan Hedberg 					       chan->dcid);
4580662d652dSJohan Hedberg 			return 0;
45816e1df6a6SAndrei Emeltchenko 		}
45826e1df6a6SAndrei Emeltchenko 
45836e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
45846e1df6a6SAndrei Emeltchenko 
45856e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
45866e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4587fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
45886e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
45896e1df6a6SAndrei Emeltchenko 	}
45906e1df6a6SAndrei Emeltchenko 
45916e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
45926e1df6a6SAndrei Emeltchenko 
45936e1df6a6SAndrei Emeltchenko 	return 0;
45946e1df6a6SAndrei Emeltchenko 
45956e1df6a6SAndrei Emeltchenko error:
4596f94ff6ffSMat Martineau 	rsp.dcid = 0;
4597f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
4598dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
4599dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4600f94ff6ffSMat Martineau 
4601f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4602f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4603f94ff6ffSMat Martineau 
4604dc280801SJohan Hedberg 	return 0;
4605f94ff6ffSMat Martineau }
4606f94ff6ffSMat Martineau 
46078eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
46088eb200bdSMat Martineau {
46098eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
46108eb200bdSMat Martineau 	u8 ident;
46118eb200bdSMat Martineau 
46128eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
46138eb200bdSMat Martineau 
46148eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
46158eb200bdSMat Martineau 	chan->ident = ident;
46168eb200bdSMat Martineau 
46178eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
46188eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
46198eb200bdSMat Martineau 
46208eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
46218eb200bdSMat Martineau 		       &req);
46228eb200bdSMat Martineau 
46238eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
46248eb200bdSMat Martineau }
46258eb200bdSMat Martineau 
46261500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
46278d5a04a1SMat Martineau {
46288d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
46298d5a04a1SMat Martineau 
46301500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46318d5a04a1SMat Martineau 
46321500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
46338d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
46348d5a04a1SMat Martineau 
46351500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
46361500109bSMat Martineau 		       sizeof(rsp), &rsp);
46378d5a04a1SMat Martineau }
46388d5a04a1SMat Martineau 
46395b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
46408d5a04a1SMat Martineau {
46418d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46428d5a04a1SMat Martineau 
46435b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
46448d5a04a1SMat Martineau 
46455b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
46468d5a04a1SMat Martineau 
46475b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
46488d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
46498d5a04a1SMat Martineau 
46505b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
46515b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46525b155ef9SMat Martineau 
46535b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
46545b155ef9SMat Martineau }
46555b155ef9SMat Martineau 
46565b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
46575b155ef9SMat Martineau {
46585b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
46595b155ef9SMat Martineau 
46605b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
46615b155ef9SMat Martineau 
46625b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
4663dcf4adbfSJoe Perches 	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
46645b155ef9SMat Martineau 
46655b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
46665b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
46678d5a04a1SMat Martineau }
46688d5a04a1SMat Martineau 
46698d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
46708d5a04a1SMat Martineau 					 u16 icid)
46718d5a04a1SMat Martineau {
46728d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
46738d5a04a1SMat Martineau 
4674ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
46758d5a04a1SMat Martineau 
46768d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
46778d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
46788d5a04a1SMat Martineau }
46798d5a04a1SMat Martineau 
46805f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
46815f3847a4SMat Martineau {
46825f3847a4SMat Martineau 	chan->hs_hchan = NULL;
46835f3847a4SMat Martineau 	chan->hs_hcon = NULL;
46845f3847a4SMat Martineau 
46855f3847a4SMat Martineau 	/* Placeholder - release the logical link */
46865f3847a4SMat Martineau }
46875f3847a4SMat Martineau 
46881500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
46891500109bSMat Martineau {
46901500109bSMat Martineau 	/* Logical link setup failed */
46911500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
46921500109bSMat Martineau 		/* Create channel failure, disconnect */
46935e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
46941500109bSMat Martineau 		return;
46951500109bSMat Martineau 	}
46961500109bSMat Martineau 
46971500109bSMat Martineau 	switch (chan->move_role) {
46981500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
46991500109bSMat Martineau 		l2cap_move_done(chan);
47001500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
47011500109bSMat Martineau 		break;
47021500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
47031500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
47041500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
47051500109bSMat Martineau 			/* Remote has only sent pending or
47061500109bSMat Martineau 			 * success responses, clean up
47071500109bSMat Martineau 			 */
47081500109bSMat Martineau 			l2cap_move_done(chan);
47091500109bSMat Martineau 		}
47101500109bSMat Martineau 
47111500109bSMat Martineau 		/* Other amp move states imply that the move
47121500109bSMat Martineau 		 * has already aborted
47131500109bSMat Martineau 		 */
47141500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
47151500109bSMat Martineau 		break;
47161500109bSMat Martineau 	}
47171500109bSMat Martineau }
47181500109bSMat Martineau 
47191500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
47201500109bSMat Martineau 					struct hci_chan *hchan)
47211500109bSMat Martineau {
47221500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
47231500109bSMat Martineau 
4724336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
47251500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
47261500109bSMat Martineau 
472735ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
47281500109bSMat Martineau 
47291500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4730fe79c6feSAndrei Emeltchenko 		int err;
47311500109bSMat Martineau 
47321500109bSMat Martineau 		set_default_fcs(chan);
47331500109bSMat Martineau 
47341500109bSMat Martineau 		err = l2cap_ertm_init(chan);
47351500109bSMat Martineau 		if (err < 0)
47365e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
47371500109bSMat Martineau 		else
47381500109bSMat Martineau 			l2cap_chan_ready(chan);
47391500109bSMat Martineau 	}
47401500109bSMat Martineau }
47411500109bSMat Martineau 
47421500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
47431500109bSMat Martineau 				      struct hci_chan *hchan)
47441500109bSMat Martineau {
47451500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
47461500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
47471500109bSMat Martineau 
47481500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
47491500109bSMat Martineau 
47501500109bSMat Martineau 	switch (chan->move_state) {
47511500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
47521500109bSMat Martineau 		/* Move confirm will be sent after a success
47531500109bSMat Martineau 		 * response is received
47541500109bSMat Martineau 		 */
47551500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
47561500109bSMat Martineau 		break;
47571500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
47581500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
47591500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
47601500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
47611500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
47621500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
47631500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
47641500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
47651500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
47661500109bSMat Martineau 		}
47671500109bSMat Martineau 		break;
47681500109bSMat Martineau 	default:
47691500109bSMat Martineau 		/* Move was not in expected state, free the channel */
47701500109bSMat Martineau 		__release_logical_link(chan);
47711500109bSMat Martineau 
47721500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
47731500109bSMat Martineau 	}
47741500109bSMat Martineau }
47751500109bSMat Martineau 
47761500109bSMat Martineau /* Call with chan locked */
477727695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
47785b155ef9SMat Martineau 		       u8 status)
47795b155ef9SMat Martineau {
47801500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
47811500109bSMat Martineau 
47821500109bSMat Martineau 	if (status) {
47831500109bSMat Martineau 		l2cap_logical_fail(chan);
47841500109bSMat Martineau 		__release_logical_link(chan);
47855b155ef9SMat Martineau 		return;
47865b155ef9SMat Martineau 	}
47875b155ef9SMat Martineau 
47881500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
47891500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
47906ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
47911500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
47921500109bSMat Martineau 	} else {
47931500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
47941500109bSMat Martineau 	}
47951500109bSMat Martineau }
47961500109bSMat Martineau 
47973f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
47983f7a56c4SMat Martineau {
47993f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
48003f7a56c4SMat Martineau 
48016ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
48023f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
48033f7a56c4SMat Martineau 			return;
48043f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
48053f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
48063f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
48073f7a56c4SMat Martineau 	} else {
48083f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
48093f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
48103f7a56c4SMat Martineau 		chan->move_id = 0;
48113f7a56c4SMat Martineau 		l2cap_move_setup(chan);
48123f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
48133f7a56c4SMat Martineau 	}
48143f7a56c4SMat Martineau }
48153f7a56c4SMat Martineau 
48168eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
48178eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
48188eb200bdSMat Martineau {
481962748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
482062748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
482162748ca1SAndrei Emeltchenko 
482212d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
482312d6cc60SAndrei Emeltchenko 
482462748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
482562748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
482662748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
482762748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
482862748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
482962748ca1SAndrei Emeltchenko 		} else {
483062748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
483162748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
483262748ca1SAndrei Emeltchenko 		}
483362748ca1SAndrei Emeltchenko 
483462748ca1SAndrei Emeltchenko 		return;
483562748ca1SAndrei Emeltchenko 	}
483662748ca1SAndrei Emeltchenko 
483762748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
483862748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
48398eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
48408eb200bdSMat Martineau 		char buf[128];
48418eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
48428eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
48438eb200bdSMat Martineau 
48448eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
48458eb200bdSMat Martineau 			/* Send successful response */
4846dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
4847dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
48488eb200bdSMat Martineau 		} else {
48498eb200bdSMat Martineau 			/* Send negative response */
4850dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
4851dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
48528eb200bdSMat Martineau 		}
48538eb200bdSMat Martineau 
48548eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
48558eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
48568eb200bdSMat Martineau 
48578eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4858f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
48598eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
48608eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
48618eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
4862e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
48638eb200bdSMat Martineau 			chan->num_conf_req++;
48648eb200bdSMat Martineau 		}
48658eb200bdSMat Martineau 	}
48668eb200bdSMat Martineau }
48678eb200bdSMat Martineau 
48688eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
48698eb200bdSMat Martineau 				   u8 remote_amp_id)
48708eb200bdSMat Martineau {
48718eb200bdSMat Martineau 	l2cap_move_setup(chan);
48728eb200bdSMat Martineau 	chan->move_id = local_amp_id;
48738eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
48748eb200bdSMat Martineau 
48758eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
48768eb200bdSMat Martineau }
48778eb200bdSMat Martineau 
48788eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
48798eb200bdSMat Martineau {
48808eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
48818eb200bdSMat Martineau 
48828eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
48838eb200bdSMat Martineau 
48848eb200bdSMat Martineau 	if (hchan) {
48858eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
48868eb200bdSMat Martineau 			/* Logical link is ready to go */
48878eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
48888eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
48898eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48908eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48918eb200bdSMat Martineau 
48928eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
48938eb200bdSMat Martineau 		} else {
48948eb200bdSMat Martineau 			/* Wait for logical link to be ready */
48958eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
48968eb200bdSMat Martineau 		}
48978eb200bdSMat Martineau 	} else {
48988eb200bdSMat Martineau 		/* Logical link not available */
48998eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
49008eb200bdSMat Martineau 	}
49018eb200bdSMat Martineau }
49028eb200bdSMat Martineau 
49038eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
49048eb200bdSMat Martineau {
49058eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
49068eb200bdSMat Martineau 		u8 rsp_result;
49078eb200bdSMat Martineau 		if (result == -EINVAL)
49088eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
49098eb200bdSMat Martineau 		else
49108eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
49118eb200bdSMat Martineau 
49128eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
49138eb200bdSMat Martineau 	}
49148eb200bdSMat Martineau 
49158eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
49168eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
49178eb200bdSMat Martineau 
49188eb200bdSMat Martineau 	/* Restart data transmission */
49198eb200bdSMat Martineau 	l2cap_ertm_send(chan);
49208eb200bdSMat Martineau }
49218eb200bdSMat Martineau 
4922a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
4923a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
49248eb200bdSMat Martineau {
4925770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
4926fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
4927770bfefaSAndrei Emeltchenko 
49288eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
49298eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
49308eb200bdSMat Martineau 
49318eb200bdSMat Martineau 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
49328eb200bdSMat Martineau 		l2cap_chan_unlock(chan);
49338eb200bdSMat Martineau 		return;
49348eb200bdSMat Martineau 	}
49358eb200bdSMat Martineau 
49368eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
49378eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
49388eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
49398eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
49408eb200bdSMat Martineau 	} else {
49418eb200bdSMat Martineau 		switch (chan->move_role) {
49428eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
49438eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
49448eb200bdSMat Martineau 					       remote_amp_id);
49458eb200bdSMat Martineau 			break;
49468eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
49478eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
49488eb200bdSMat Martineau 			break;
49498eb200bdSMat Martineau 		default:
49508eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
49518eb200bdSMat Martineau 			break;
49528eb200bdSMat Martineau 		}
49538eb200bdSMat Martineau 	}
49548eb200bdSMat Martineau }
49558eb200bdSMat Martineau 
49568d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
4957ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
4958ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
49598d5a04a1SMat Martineau {
49608d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
49611500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
496202b0fbb9SMat Martineau 	struct l2cap_chan *chan;
49638d5a04a1SMat Martineau 	u16 icid = 0;
49648d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
49658d5a04a1SMat Martineau 
49668d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
49678d5a04a1SMat Martineau 		return -EPROTO;
49688d5a04a1SMat Martineau 
49698d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
49708d5a04a1SMat Martineau 
4971ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
49728d5a04a1SMat Martineau 
49730bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
49748d5a04a1SMat Martineau 		return -EINVAL;
49758d5a04a1SMat Martineau 
497602b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
497702b0fbb9SMat Martineau 	if (!chan) {
49781500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
4979dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
49801500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
49811500109bSMat Martineau 			       sizeof(rsp), &rsp);
498202b0fbb9SMat Martineau 		return 0;
498302b0fbb9SMat Martineau 	}
498402b0fbb9SMat Martineau 
49851500109bSMat Martineau 	chan->ident = cmd->ident;
49861500109bSMat Martineau 
498702b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
498802b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
498902b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
499002b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
499102b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
499202b0fbb9SMat Martineau 		goto send_move_response;
499302b0fbb9SMat Martineau 	}
499402b0fbb9SMat Martineau 
499502b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
499602b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
499702b0fbb9SMat Martineau 		goto send_move_response;
499802b0fbb9SMat Martineau 	}
499902b0fbb9SMat Martineau 
50006ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
500102b0fbb9SMat Martineau 		struct hci_dev *hdev;
500202b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
500302b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
500402b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
500502b0fbb9SMat Martineau 			if (hdev)
500602b0fbb9SMat Martineau 				hci_dev_put(hdev);
500702b0fbb9SMat Martineau 
500802b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
500902b0fbb9SMat Martineau 			goto send_move_response;
501002b0fbb9SMat Martineau 		}
501102b0fbb9SMat Martineau 		hci_dev_put(hdev);
501202b0fbb9SMat Martineau 	}
501302b0fbb9SMat Martineau 
501402b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
501502b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
501602b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
501702b0fbb9SMat Martineau 	 */
501802b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
501902b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
50206f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
502102b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
502202b0fbb9SMat Martineau 		goto send_move_response;
502302b0fbb9SMat Martineau 	}
502402b0fbb9SMat Martineau 
502502b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
502602b0fbb9SMat Martineau 	l2cap_move_setup(chan);
502702b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
502802b0fbb9SMat Martineau 	icid = chan->dcid;
502902b0fbb9SMat Martineau 
50306ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
503102b0fbb9SMat Martineau 		/* Moving to BR/EDR */
503202b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
503302b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
503402b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
503502b0fbb9SMat Martineau 		} else {
503602b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
503702b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
503802b0fbb9SMat Martineau 		}
503902b0fbb9SMat Martineau 	} else {
504002b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
504102b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
504202b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
504302b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
504402b0fbb9SMat Martineau 	}
504502b0fbb9SMat Martineau 
504602b0fbb9SMat Martineau send_move_response:
50471500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
50488d5a04a1SMat Martineau 
504902b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
505002b0fbb9SMat Martineau 
50518d5a04a1SMat Martineau 	return 0;
50528d5a04a1SMat Martineau }
50538d5a04a1SMat Martineau 
50545b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
50555b155ef9SMat Martineau {
50565b155ef9SMat Martineau 	struct l2cap_chan *chan;
50575b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
50585b155ef9SMat Martineau 
50595b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
50605b155ef9SMat Martineau 	if (!chan) {
50615b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
50625b155ef9SMat Martineau 		return;
50635b155ef9SMat Martineau 	}
50645b155ef9SMat Martineau 
50655b155ef9SMat Martineau 	__clear_chan_timer(chan);
50665b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
50675b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
50685b155ef9SMat Martineau 
50695b155ef9SMat Martineau 	switch (chan->move_state) {
50705b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50715b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
50725b155ef9SMat Martineau 		 * is complete.
50735b155ef9SMat Martineau 		 */
50745b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50755b155ef9SMat Martineau 		break;
50765b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
50775b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
50785b155ef9SMat Martineau 			break;
50795b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
50805b155ef9SMat Martineau 				    &chan->conn_state)) {
50815b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50825b155ef9SMat Martineau 		} else {
50835b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
50845b155ef9SMat Martineau 			 * proceed with move
50855b155ef9SMat Martineau 			 */
50865b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50875b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50885b155ef9SMat Martineau 		}
50895b155ef9SMat Martineau 		break;
50905b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
50915b155ef9SMat Martineau 		/* Moving to AMP */
50925b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
50935b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
50945b155ef9SMat Martineau 			 * after logical link is ready
50955b155ef9SMat Martineau 			 */
50965b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50975b155ef9SMat Martineau 		} else {
50985b155ef9SMat Martineau 			/* Both logical link and move success
50995b155ef9SMat Martineau 			 * are required to confirm
51005b155ef9SMat Martineau 			 */
51015b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
51025b155ef9SMat Martineau 		}
51035b155ef9SMat Martineau 
51045b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
51055b155ef9SMat Martineau 		if (!hchan) {
51065b155ef9SMat Martineau 			/* Logical link not available */
51075b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51085b155ef9SMat Martineau 			break;
51095b155ef9SMat Martineau 		}
51105b155ef9SMat Martineau 
51115b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
51125b155ef9SMat Martineau 		 * send confirmation.
51135b155ef9SMat Martineau 		 */
51145b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
51155b155ef9SMat Martineau 			break;
51165b155ef9SMat Martineau 
51175b155ef9SMat Martineau 		/* Logical link is already ready to go */
51185b155ef9SMat Martineau 
51195b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
51205b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
51215b155ef9SMat Martineau 
51225b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
51235b155ef9SMat Martineau 			/* Can confirm now */
51245b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
51255b155ef9SMat Martineau 		} else {
51265b155ef9SMat Martineau 			/* Now only need move success
51275b155ef9SMat Martineau 			 * to confirm
51285b155ef9SMat Martineau 			 */
51295b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
51305b155ef9SMat Martineau 		}
51315b155ef9SMat Martineau 
51325b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
51335b155ef9SMat Martineau 		break;
51345b155ef9SMat Martineau 	default:
51355b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
51365b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
51375b155ef9SMat Martineau 		l2cap_move_done(chan);
51385b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51395b155ef9SMat Martineau 	}
51405b155ef9SMat Martineau 
51415b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51425b155ef9SMat Martineau }
51435b155ef9SMat Martineau 
51445b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
51455b155ef9SMat Martineau 			    u16 result)
51465b155ef9SMat Martineau {
51475b155ef9SMat Martineau 	struct l2cap_chan *chan;
51485b155ef9SMat Martineau 
51495b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
51505b155ef9SMat Martineau 	if (!chan) {
51515b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
51525b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51535b155ef9SMat Martineau 		return;
51545b155ef9SMat Martineau 	}
51555b155ef9SMat Martineau 
51565b155ef9SMat Martineau 	__clear_chan_timer(chan);
51575b155ef9SMat Martineau 
51585b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
51595b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
51605b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
51615b155ef9SMat Martineau 		} else {
51625b155ef9SMat Martineau 			/* Cleanup - cancel move */
51635b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
51645b155ef9SMat Martineau 			l2cap_move_done(chan);
51655b155ef9SMat Martineau 		}
51665b155ef9SMat Martineau 	}
51675b155ef9SMat Martineau 
51685b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
51695b155ef9SMat Martineau 
51705b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
51715b155ef9SMat Martineau }
51725b155ef9SMat Martineau 
51735b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5174ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5175ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
51768d5a04a1SMat Martineau {
51778d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
51788d5a04a1SMat Martineau 	u16 icid, result;
51798d5a04a1SMat Martineau 
51808d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
51818d5a04a1SMat Martineau 		return -EPROTO;
51828d5a04a1SMat Martineau 
51838d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
51848d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
51858d5a04a1SMat Martineau 
5186ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
51878d5a04a1SMat Martineau 
51885b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
51895b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
51905b155ef9SMat Martineau 	else
51915b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
51928d5a04a1SMat Martineau 
51938d5a04a1SMat Martineau 	return 0;
51948d5a04a1SMat Martineau }
51958d5a04a1SMat Martineau 
51965f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5197ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5198ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
51998d5a04a1SMat Martineau {
52008d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
52015f3847a4SMat Martineau 	struct l2cap_chan *chan;
52028d5a04a1SMat Martineau 	u16 icid, result;
52038d5a04a1SMat Martineau 
52048d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
52058d5a04a1SMat Martineau 		return -EPROTO;
52068d5a04a1SMat Martineau 
52078d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
52088d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
52098d5a04a1SMat Martineau 
5210ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
52118d5a04a1SMat Martineau 
52125f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
52135f3847a4SMat Martineau 	if (!chan) {
52145f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
52158d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
52165f3847a4SMat Martineau 		return 0;
52175f3847a4SMat Martineau 	}
52185f3847a4SMat Martineau 
52195f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
52205f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
52215f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
52226ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
52235f3847a4SMat Martineau 				__release_logical_link(chan);
52245f3847a4SMat Martineau 		} else {
52255f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
52265f3847a4SMat Martineau 		}
52275f3847a4SMat Martineau 
52285f3847a4SMat Martineau 		l2cap_move_done(chan);
52295f3847a4SMat Martineau 	}
52305f3847a4SMat Martineau 
52315f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
52325f3847a4SMat Martineau 
52335f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
52348d5a04a1SMat Martineau 
52358d5a04a1SMat Martineau 	return 0;
52368d5a04a1SMat Martineau }
52378d5a04a1SMat Martineau 
52388d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5239ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5240ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
52418d5a04a1SMat Martineau {
52428d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
52433fd71a0aSMat Martineau 	struct l2cap_chan *chan;
52448d5a04a1SMat Martineau 	u16 icid;
52458d5a04a1SMat Martineau 
52468d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
52478d5a04a1SMat Martineau 		return -EPROTO;
52488d5a04a1SMat Martineau 
52498d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
52508d5a04a1SMat Martineau 
5251ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
52528d5a04a1SMat Martineau 
52533fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
52543fd71a0aSMat Martineau 	if (!chan)
52553fd71a0aSMat Martineau 		return 0;
52563fd71a0aSMat Martineau 
52573fd71a0aSMat Martineau 	__clear_chan_timer(chan);
52583fd71a0aSMat Martineau 
52593fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
52603fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
52613fd71a0aSMat Martineau 
52626ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
52633fd71a0aSMat Martineau 			__release_logical_link(chan);
52643fd71a0aSMat Martineau 
52653fd71a0aSMat Martineau 		l2cap_move_done(chan);
52663fd71a0aSMat Martineau 	}
52673fd71a0aSMat Martineau 
52683fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
52693fd71a0aSMat Martineau 
52708d5a04a1SMat Martineau 	return 0;
52718d5a04a1SMat Martineau }
52728d5a04a1SMat Martineau 
5273de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
52742d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5275203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5276de73115aSClaudio Takahasi {
5277de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5278de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5279de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5280203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
52812ce603ebSClaudio Takahasi 	int err;
5282de73115aSClaudio Takahasi 
528340bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
5284de73115aSClaudio Takahasi 		return -EINVAL;
5285de73115aSClaudio Takahasi 
5286de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5287de73115aSClaudio Takahasi 		return -EPROTO;
5288de73115aSClaudio Takahasi 
5289de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5290de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5291de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5292de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5293de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5294de73115aSClaudio Takahasi 
5295de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5296de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5297de73115aSClaudio Takahasi 
5298de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
52992ce603ebSClaudio Takahasi 
5300d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
53012ce603ebSClaudio Takahasi 	if (err)
5302dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5303de73115aSClaudio Takahasi 	else
5304dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5305de73115aSClaudio Takahasi 
5306de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5307de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5308de73115aSClaudio Takahasi 
5309ffb5a827SAndre Guedes 	if (!err) {
5310f4869e2aSJohan Hedberg 		u8 store_hint;
5311ffb5a827SAndre Guedes 
5312f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
5313f4869e2aSJohan Hedberg 						to_multiplier);
5314f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
5315f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
5316f4869e2aSJohan Hedberg 				    to_multiplier);
5317f4869e2aSJohan Hedberg 
5318ffb5a827SAndre Guedes 	}
53192ce603ebSClaudio Takahasi 
5320de73115aSClaudio Takahasi 	return 0;
5321de73115aSClaudio Takahasi }
5322de73115aSClaudio Takahasi 
5323f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5324f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5325f1496deeSJohan Hedberg 				u8 *data)
5326f1496deeSJohan Hedberg {
5327f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
53283e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
5329f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5330f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
53313e64b7bdSJohan Hedberg 	int err, sec_level;
5332f1496deeSJohan Hedberg 
5333f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5334f1496deeSJohan Hedberg 		return -EPROTO;
5335f1496deeSJohan Hedberg 
5336f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5337f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5338f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5339f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5340f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5341f1496deeSJohan Hedberg 
5342571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
534340624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
534440624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
5345f1496deeSJohan Hedberg 		return -EPROTO;
5346f1496deeSJohan Hedberg 
5347f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5348f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5349f1496deeSJohan Hedberg 
5350f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5351f1496deeSJohan Hedberg 
5352f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5353f1496deeSJohan Hedberg 	if (!chan) {
5354f1496deeSJohan Hedberg 		err = -EBADSLT;
5355f1496deeSJohan Hedberg 		goto unlock;
5356f1496deeSJohan Hedberg 	}
5357f1496deeSJohan Hedberg 
5358f1496deeSJohan Hedberg 	err = 0;
5359f1496deeSJohan Hedberg 
5360f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5361f1496deeSJohan Hedberg 
5362f1496deeSJohan Hedberg 	switch (result) {
5363571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
536440624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
536540624183SJohan Hedberg 			err = -EBADSLT;
536640624183SJohan Hedberg 			break;
536740624183SJohan Hedberg 		}
536840624183SJohan Hedberg 
5369f1496deeSJohan Hedberg 		chan->ident = 0;
5370f1496deeSJohan Hedberg 		chan->dcid = dcid;
5371f1496deeSJohan Hedberg 		chan->omtu = mtu;
5372f1496deeSJohan Hedberg 		chan->remote_mps = mps;
53730cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5374f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5375f1496deeSJohan Hedberg 		break;
5376f1496deeSJohan Hedberg 
5377571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
5378571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
53793e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
53803e64b7bdSJohan Hedberg 		 * anything.
53813e64b7bdSJohan Hedberg 		 */
53823e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
53833e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
53843e64b7bdSJohan Hedberg 			break;
53853e64b7bdSJohan Hedberg 		}
53863e64b7bdSJohan Hedberg 
53873e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
53883e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
53893e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
53903e64b7bdSJohan Hedberg 
53913e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
53923e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
53933e64b7bdSJohan Hedberg 
53943e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
53953e64b7bdSJohan Hedberg 		break;
53963e64b7bdSJohan Hedberg 
5397f1496deeSJohan Hedberg 	default:
5398f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5399f1496deeSJohan Hedberg 		break;
5400f1496deeSJohan Hedberg 	}
5401f1496deeSJohan Hedberg 
5402f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5403f1496deeSJohan Hedberg 
5404f1496deeSJohan Hedberg unlock:
5405f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5406f1496deeSJohan Hedberg 
5407f1496deeSJohan Hedberg 	return err;
5408f1496deeSJohan Hedberg }
5409f1496deeSJohan Hedberg 
54103300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
54112d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
54122d792818SGustavo Padovan 				      u8 *data)
54133300d9a9SClaudio Takahasi {
54143300d9a9SClaudio Takahasi 	int err = 0;
54153300d9a9SClaudio Takahasi 
54163300d9a9SClaudio Takahasi 	switch (cmd->code) {
54173300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5418cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
54193300d9a9SClaudio Takahasi 		break;
54203300d9a9SClaudio Takahasi 
54213300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5422cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
54233300d9a9SClaudio Takahasi 		break;
54243300d9a9SClaudio Takahasi 
54253300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5426f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
54279245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
54283300d9a9SClaudio Takahasi 		break;
54293300d9a9SClaudio Takahasi 
54303300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
54313300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
54323300d9a9SClaudio Takahasi 		break;
54333300d9a9SClaudio Takahasi 
54343300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
54359245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
54363300d9a9SClaudio Takahasi 		break;
54373300d9a9SClaudio Takahasi 
54383300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5439cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
54403300d9a9SClaudio Takahasi 		break;
54413300d9a9SClaudio Takahasi 
54423300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
54439245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
54443300d9a9SClaudio Takahasi 		break;
54453300d9a9SClaudio Takahasi 
54463300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
54473300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
54483300d9a9SClaudio Takahasi 		break;
54493300d9a9SClaudio Takahasi 
54503300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
54513300d9a9SClaudio Takahasi 		break;
54523300d9a9SClaudio Takahasi 
54533300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5454cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
54553300d9a9SClaudio Takahasi 		break;
54563300d9a9SClaudio Takahasi 
54573300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
54589245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
54593300d9a9SClaudio Takahasi 		break;
54603300d9a9SClaudio Takahasi 
5461f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5462f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5463f94ff6ffSMat Martineau 		break;
5464f94ff6ffSMat Martineau 
54658d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
54668d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
54678d5a04a1SMat Martineau 		break;
54688d5a04a1SMat Martineau 
54698d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
54709245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
54718d5a04a1SMat Martineau 		break;
54728d5a04a1SMat Martineau 
54738d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
54748d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
54758d5a04a1SMat Martineau 		break;
54768d5a04a1SMat Martineau 
54778d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
54789245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
54798d5a04a1SMat Martineau 		break;
54808d5a04a1SMat Martineau 
54813300d9a9SClaudio Takahasi 	default:
54823300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
54833300d9a9SClaudio Takahasi 		err = -EINVAL;
54843300d9a9SClaudio Takahasi 		break;
54853300d9a9SClaudio Takahasi 	}
54863300d9a9SClaudio Takahasi 
54873300d9a9SClaudio Takahasi 	return err;
54883300d9a9SClaudio Takahasi }
54893300d9a9SClaudio Takahasi 
549027e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
549127e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
549227e2d4c8SJohan Hedberg 				u8 *data)
549327e2d4c8SJohan Hedberg {
549427e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
549527e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
549627e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
54970cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
549827e2d4c8SJohan Hedberg 	__le16 psm;
549927e2d4c8SJohan Hedberg 	u8 result;
550027e2d4c8SJohan Hedberg 
550127e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
550227e2d4c8SJohan Hedberg 		return -EPROTO;
550327e2d4c8SJohan Hedberg 
550427e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
550527e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
550627e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
550727e2d4c8SJohan Hedberg 	psm  = req->psm;
550827e2d4c8SJohan Hedberg 	dcid = 0;
55090cd75f7eSJohan Hedberg 	credits = 0;
551027e2d4c8SJohan Hedberg 
551127e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
551227e2d4c8SJohan Hedberg 		return -EPROTO;
551327e2d4c8SJohan Hedberg 
551427e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
551527e2d4c8SJohan Hedberg 	       scid, mtu, mps);
551627e2d4c8SJohan Hedberg 
551727e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
551827e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
551927e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
552027e2d4c8SJohan Hedberg 	if (!pchan) {
5521571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
552227e2d4c8SJohan Hedberg 		chan = NULL;
552327e2d4c8SJohan Hedberg 		goto response;
552427e2d4c8SJohan Hedberg 	}
552527e2d4c8SJohan Hedberg 
552627e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
552727e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
552827e2d4c8SJohan Hedberg 
552935dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
553035dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
5531571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
553227e2d4c8SJohan Hedberg 		chan = NULL;
553327e2d4c8SJohan Hedberg 		goto response_unlock;
553427e2d4c8SJohan Hedberg 	}
553527e2d4c8SJohan Hedberg 
55368a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
55378a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
5538571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
55398a7889ccSJohan Hedberg 		chan = NULL;
55408a7889ccSJohan Hedberg 		goto response_unlock;
55418a7889ccSJohan Hedberg 	}
55428a7889ccSJohan Hedberg 
554327e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
554427e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
5545571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
554627e2d4c8SJohan Hedberg 		chan = NULL;
554727e2d4c8SJohan Hedberg 		goto response_unlock;
554827e2d4c8SJohan Hedberg 	}
554927e2d4c8SJohan Hedberg 
555027e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
555127e2d4c8SJohan Hedberg 	if (!chan) {
5552571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
555327e2d4c8SJohan Hedberg 		goto response_unlock;
555427e2d4c8SJohan Hedberg 	}
555527e2d4c8SJohan Hedberg 
555627e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
555727e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
5558a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
5559a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
556027e2d4c8SJohan Hedberg 	chan->psm  = psm;
556127e2d4c8SJohan Hedberg 	chan->dcid = scid;
556227e2d4c8SJohan Hedberg 	chan->omtu = mtu;
556327e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
556427e2d4c8SJohan Hedberg 
556527e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
5566fe149310SLuiz Augusto von Dentz 
5567ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
5568fe149310SLuiz Augusto von Dentz 
556927e2d4c8SJohan Hedberg 	dcid = chan->scid;
55700cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
557127e2d4c8SJohan Hedberg 
557227e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
557327e2d4c8SJohan Hedberg 
557427e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
557527e2d4c8SJohan Hedberg 
557627e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
557727e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
5578434714dcSJohan Hedberg 		/* The following result value is actually not defined
5579434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
5580434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
5581434714dcSJohan Hedberg 		 * instead of sending a response.
5582434714dcSJohan Hedberg 		 */
558327e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
558427e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
558527e2d4c8SJohan Hedberg 	} else {
558627e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
5587571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
558827e2d4c8SJohan Hedberg 	}
558927e2d4c8SJohan Hedberg 
559027e2d4c8SJohan Hedberg response_unlock:
559127e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
559227e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5593a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
559427e2d4c8SJohan Hedberg 
559527e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
559627e2d4c8SJohan Hedberg 		return 0;
559727e2d4c8SJohan Hedberg 
559827e2d4c8SJohan Hedberg response:
559927e2d4c8SJohan Hedberg 	if (chan) {
560027e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
56013916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
560227e2d4c8SJohan Hedberg 	} else {
560327e2d4c8SJohan Hedberg 		rsp.mtu = 0;
560427e2d4c8SJohan Hedberg 		rsp.mps = 0;
560527e2d4c8SJohan Hedberg 	}
560627e2d4c8SJohan Hedberg 
560727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
56080cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
560927e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
561027e2d4c8SJohan Hedberg 
561127e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
561227e2d4c8SJohan Hedberg 
561327e2d4c8SJohan Hedberg 	return 0;
561427e2d4c8SJohan Hedberg }
561527e2d4c8SJohan Hedberg 
5616fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5617fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5618fad5fc89SJohan Hedberg 				   u8 *data)
5619fad5fc89SJohan Hedberg {
5620fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5621fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
56220f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
5623fad5fc89SJohan Hedberg 
5624fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5625fad5fc89SJohan Hedberg 		return -EPROTO;
5626fad5fc89SJohan Hedberg 
5627fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5628fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5629fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5630fad5fc89SJohan Hedberg 
5631fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5632fad5fc89SJohan Hedberg 
5633fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5634fad5fc89SJohan Hedberg 	if (!chan)
5635fad5fc89SJohan Hedberg 		return -EBADSLT;
5636fad5fc89SJohan Hedberg 
56370f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
56380f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
56390f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
56400f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
5641ee93053dSMartin Townsend 		l2cap_chan_unlock(chan);
56420f1bfe4eSJohan Hedberg 
56430f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
56440f1bfe4eSJohan Hedberg 		 * command reject packet.
56450f1bfe4eSJohan Hedberg 		 */
56460f1bfe4eSJohan Hedberg 		return 0;
56470f1bfe4eSJohan Hedberg 	}
56480f1bfe4eSJohan Hedberg 
5649fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5650fad5fc89SJohan Hedberg 
56518a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
56528a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
5653fad5fc89SJohan Hedberg 
5654fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5655fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5656fad5fc89SJohan Hedberg 
5657fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5658fad5fc89SJohan Hedberg 
5659fad5fc89SJohan Hedberg 	return 0;
5660fad5fc89SJohan Hedberg }
5661fad5fc89SJohan Hedberg 
566271fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
566371fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
566471fb4197SJohan Hedberg 				       u8 *data)
566571fb4197SJohan Hedberg {
566671fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
566771fb4197SJohan Hedberg 	struct l2cap_chan *chan;
566871fb4197SJohan Hedberg 
566971fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
567071fb4197SJohan Hedberg 		return -EPROTO;
567171fb4197SJohan Hedberg 
567271fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
567371fb4197SJohan Hedberg 
567471fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
567571fb4197SJohan Hedberg 	if (!chan)
567671fb4197SJohan Hedberg 		goto done;
567771fb4197SJohan Hedberg 
567871fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
567971fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
568071fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
568171fb4197SJohan Hedberg 
568271fb4197SJohan Hedberg done:
568371fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
568471fb4197SJohan Hedberg 	return 0;
568571fb4197SJohan Hedberg }
568671fb4197SJohan Hedberg 
56873300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5688203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5689203e639eSJohan Hedberg 				   u8 *data)
56903300d9a9SClaudio Takahasi {
5691b5ecba64SJohan Hedberg 	int err = 0;
5692b5ecba64SJohan Hedberg 
56933300d9a9SClaudio Takahasi 	switch (cmd->code) {
56943300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
569571fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
5696b5ecba64SJohan Hedberg 		break;
56973300d9a9SClaudio Takahasi 
56983300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5699b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5700b5ecba64SJohan Hedberg 		break;
57013300d9a9SClaudio Takahasi 
57023300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5703b5ecba64SJohan Hedberg 		break;
57043300d9a9SClaudio Takahasi 
5705f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5706f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5707b5ecba64SJohan Hedberg 		break;
5708f1496deeSJohan Hedberg 
570927e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5710b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5711b5ecba64SJohan Hedberg 		break;
571227e2d4c8SJohan Hedberg 
5713fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5714fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5715fad5fc89SJohan Hedberg 		break;
5716fad5fc89SJohan Hedberg 
57173defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5718b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5719b5ecba64SJohan Hedberg 		break;
57203defe01aSJohan Hedberg 
57213defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
57223defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5723b5ecba64SJohan Hedberg 		break;
57243defe01aSJohan Hedberg 
57253300d9a9SClaudio Takahasi 	default:
57263300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5727b5ecba64SJohan Hedberg 		err = -EINVAL;
5728b5ecba64SJohan Hedberg 		break;
57293300d9a9SClaudio Takahasi 	}
5730b5ecba64SJohan Hedberg 
5731b5ecba64SJohan Hedberg 	return err;
57323300d9a9SClaudio Takahasi }
57333300d9a9SClaudio Takahasi 
5734c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5735c5623556SJohan Hedberg 					struct sk_buff *skb)
5736c5623556SJohan Hedberg {
573769c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
57384f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
57394f3e219dSMarcel Holtmann 	u16 len;
5740c5623556SJohan Hedberg 	int err;
5741c5623556SJohan Hedberg 
574269c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
57433b166295SMarcel Holtmann 		goto drop;
574469c4e4e8SJohan Hedberg 
57454f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
57464f3e219dSMarcel Holtmann 		goto drop;
5747c5623556SJohan Hedberg 
57484f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
57494f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5750c5623556SJohan Hedberg 
57514f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5752c5623556SJohan Hedberg 
57534f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
57544f3e219dSMarcel Holtmann 
57554f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5756c5623556SJohan Hedberg 		BT_DBG("corrupted command");
57574f3e219dSMarcel Holtmann 		goto drop;
5758c5623556SJohan Hedberg 	}
5759c5623556SJohan Hedberg 
5760203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5761c5623556SJohan Hedberg 	if (err) {
5762c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5763c5623556SJohan Hedberg 
5764c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5765c5623556SJohan Hedberg 
5766dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
57674f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5768c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5769c5623556SJohan Hedberg 	}
5770c5623556SJohan Hedberg 
57713b166295SMarcel Holtmann drop:
5772c5623556SJohan Hedberg 	kfree_skb(skb);
5773c5623556SJohan Hedberg }
5774c5623556SJohan Hedberg 
57753300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
57763300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
57770a708f8fSGustavo F. Padovan {
577869c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
57790a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
57800a708f8fSGustavo F. Padovan 	int len = skb->len;
57810a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
57823300d9a9SClaudio Takahasi 	int err;
57830a708f8fSGustavo F. Padovan 
57840a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
57850a708f8fSGustavo F. Padovan 
578669c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
57873b166295SMarcel Holtmann 		goto drop;
578869c4e4e8SJohan Hedberg 
57890a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
57900a708f8fSGustavo F. Padovan 		u16 cmd_len;
57910a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
57920a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
57930a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
57940a708f8fSGustavo F. Padovan 
57950a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
57960a708f8fSGustavo F. Padovan 
57972d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
57982d792818SGustavo Padovan 		       cmd.ident);
57990a708f8fSGustavo F. Padovan 
58000a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
58010a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
58020a708f8fSGustavo F. Padovan 			break;
58030a708f8fSGustavo F. Padovan 		}
58040a708f8fSGustavo F. Padovan 
58053300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
58060a708f8fSGustavo F. Padovan 		if (err) {
5807e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
58082c6d1a2eSGustavo F. Padovan 
58092c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
58100a708f8fSGustavo F. Padovan 
5811dcf4adbfSJoe Perches 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58122d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
58132d792818SGustavo Padovan 				       sizeof(rej), &rej);
58140a708f8fSGustavo F. Padovan 		}
58150a708f8fSGustavo F. Padovan 
58160a708f8fSGustavo F. Padovan 		data += cmd_len;
58170a708f8fSGustavo F. Padovan 		len  -= cmd_len;
58180a708f8fSGustavo F. Padovan 	}
58190a708f8fSGustavo F. Padovan 
58203b166295SMarcel Holtmann drop:
58210a708f8fSGustavo F. Padovan 	kfree_skb(skb);
58220a708f8fSGustavo F. Padovan }
58230a708f8fSGustavo F. Padovan 
582447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
58250a708f8fSGustavo F. Padovan {
58260a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5827e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5828e4ca6d98SAndrei Emeltchenko 
5829e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5830e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5831e4ca6d98SAndrei Emeltchenko 	else
5832e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
58330a708f8fSGustavo F. Padovan 
583447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
583503a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
58360a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
58370a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
58380a708f8fSGustavo F. Padovan 
58390a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
58400a708f8fSGustavo F. Padovan 			return -EBADMSG;
58410a708f8fSGustavo F. Padovan 	}
58420a708f8fSGustavo F. Padovan 	return 0;
58430a708f8fSGustavo F. Padovan }
58440a708f8fSGustavo F. Padovan 
58456ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
58460a708f8fSGustavo F. Padovan {
5847e31f7633SMat Martineau 	struct l2cap_ctrl control;
58480a708f8fSGustavo F. Padovan 
5849e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
58500a708f8fSGustavo F. Padovan 
5851e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5852e31f7633SMat Martineau 	control.sframe = 1;
5853e31f7633SMat Martineau 	control.final = 1;
5854e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5855e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
58560a708f8fSGustavo F. Padovan 
5857e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5858e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5859e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
58600a708f8fSGustavo F. Padovan 	}
58610a708f8fSGustavo F. Padovan 
5862e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5863e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5864e31f7633SMat Martineau 		__set_retrans_timer(chan);
58650a708f8fSGustavo F. Padovan 
5866e31f7633SMat Martineau 	/* Send pending iframes */
5867525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
58680a708f8fSGustavo F. Padovan 
5869e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5870e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5871e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5872e31f7633SMat Martineau 		 * send it now.
5873e31f7633SMat Martineau 		 */
5874e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5875e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
58760a708f8fSGustavo F. Padovan 	}
58770a708f8fSGustavo F. Padovan }
58780a708f8fSGustavo F. Padovan 
58792d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
58802d792818SGustavo Padovan 			    struct sk_buff **last_frag)
58810a708f8fSGustavo F. Padovan {
588284084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
588384084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
588484084a31SMat Martineau 	 */
588584084a31SMat Martineau 	if (!skb_has_frag_list(skb))
588684084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
588784084a31SMat Martineau 
588884084a31SMat Martineau 	new_frag->next = NULL;
588984084a31SMat Martineau 
589084084a31SMat Martineau 	(*last_frag)->next = new_frag;
589184084a31SMat Martineau 	*last_frag = new_frag;
589284084a31SMat Martineau 
589384084a31SMat Martineau 	skb->len += new_frag->len;
589484084a31SMat Martineau 	skb->data_len += new_frag->len;
589584084a31SMat Martineau 	skb->truesize += new_frag->truesize;
589684084a31SMat Martineau }
589784084a31SMat Martineau 
58984b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
58994b51dae9SMat Martineau 				struct l2cap_ctrl *control)
590084084a31SMat Martineau {
590184084a31SMat Martineau 	int err = -EINVAL;
59020a708f8fSGustavo F. Padovan 
59034b51dae9SMat Martineau 	switch (control->sar) {
59047e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
590584084a31SMat Martineau 		if (chan->sdu)
590684084a31SMat Martineau 			break;
59070a708f8fSGustavo F. Padovan 
590880b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
590984084a31SMat Martineau 		break;
59100a708f8fSGustavo F. Padovan 
59117e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
591284084a31SMat Martineau 		if (chan->sdu)
591384084a31SMat Martineau 			break;
59140a708f8fSGustavo F. Padovan 
5915dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
5916dbb50887SDaniel Borkmann 			break;
5917dbb50887SDaniel Borkmann 
59186f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
591903a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
59200a708f8fSGustavo F. Padovan 
592184084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
592284084a31SMat Martineau 			err = -EMSGSIZE;
592384084a31SMat Martineau 			break;
592484084a31SMat Martineau 		}
59250a708f8fSGustavo F. Padovan 
592684084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
592784084a31SMat Martineau 			break;
592884084a31SMat Martineau 
592984084a31SMat Martineau 		chan->sdu = skb;
593084084a31SMat Martineau 		chan->sdu_last_frag = skb;
593184084a31SMat Martineau 
593284084a31SMat Martineau 		skb = NULL;
593384084a31SMat Martineau 		err = 0;
59340a708f8fSGustavo F. Padovan 		break;
59350a708f8fSGustavo F. Padovan 
59367e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
59376f61fd47SGustavo F. Padovan 		if (!chan->sdu)
593884084a31SMat Martineau 			break;
59390a708f8fSGustavo F. Padovan 
594084084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
594184084a31SMat Martineau 				&chan->sdu_last_frag);
594284084a31SMat Martineau 		skb = NULL;
59430a708f8fSGustavo F. Padovan 
594484084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
594584084a31SMat Martineau 			break;
59460a708f8fSGustavo F. Padovan 
594784084a31SMat Martineau 		err = 0;
59480a708f8fSGustavo F. Padovan 		break;
59490a708f8fSGustavo F. Padovan 
59507e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
59516f61fd47SGustavo F. Padovan 		if (!chan->sdu)
595284084a31SMat Martineau 			break;
59530a708f8fSGustavo F. Padovan 
595484084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
595584084a31SMat Martineau 				&chan->sdu_last_frag);
595684084a31SMat Martineau 		skb = NULL;
59570a708f8fSGustavo F. Padovan 
595884084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
595984084a31SMat Martineau 			break;
59600a708f8fSGustavo F. Padovan 
596180b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
59620a708f8fSGustavo F. Padovan 
596384084a31SMat Martineau 		if (!err) {
596484084a31SMat Martineau 			/* Reassembly complete */
596584084a31SMat Martineau 			chan->sdu = NULL;
596684084a31SMat Martineau 			chan->sdu_last_frag = NULL;
596784084a31SMat Martineau 			chan->sdu_len = 0;
59680a708f8fSGustavo F. Padovan 		}
59690a708f8fSGustavo F. Padovan 		break;
59700a708f8fSGustavo F. Padovan 	}
59710a708f8fSGustavo F. Padovan 
597284084a31SMat Martineau 	if (err) {
59730a708f8fSGustavo F. Padovan 		kfree_skb(skb);
59746f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
59756f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
597684084a31SMat Martineau 		chan->sdu_last_frag = NULL;
597784084a31SMat Martineau 		chan->sdu_len = 0;
597884084a31SMat Martineau 	}
59790a708f8fSGustavo F. Padovan 
598084084a31SMat Martineau 	return err;
59810a708f8fSGustavo F. Padovan }
59820a708f8fSGustavo F. Padovan 
598332b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
598432b32735SMat Martineau {
598532b32735SMat Martineau 	/* Placeholder */
598632b32735SMat Martineau 	return 0;
598732b32735SMat Martineau }
598832b32735SMat Martineau 
5989e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
59900a708f8fSGustavo F. Padovan {
599161aa4f5bSMat Martineau 	u8 event;
599261aa4f5bSMat Martineau 
599361aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
599461aa4f5bSMat Martineau 		return;
599561aa4f5bSMat Martineau 
599661aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
5997401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
59980a708f8fSGustavo F. Padovan }
59990a708f8fSGustavo F. Padovan 
6000d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6001d2a7ac5dSMat Martineau {
600263838725SMat Martineau 	int err = 0;
600363838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
600463838725SMat Martineau 	 * until a gap is encountered.
600563838725SMat Martineau 	 */
600663838725SMat Martineau 
600763838725SMat Martineau 	BT_DBG("chan %p", chan);
600863838725SMat Martineau 
600963838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
601063838725SMat Martineau 		struct sk_buff *skb;
601163838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
601263838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
601363838725SMat Martineau 
601463838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
601563838725SMat Martineau 
601663838725SMat Martineau 		if (!skb)
601763838725SMat Martineau 			break;
601863838725SMat Martineau 
601963838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
602063838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
6021a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
602263838725SMat Martineau 		if (err)
602363838725SMat Martineau 			break;
602463838725SMat Martineau 	}
602563838725SMat Martineau 
602663838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
602763838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
602863838725SMat Martineau 		l2cap_send_ack(chan);
602963838725SMat Martineau 	}
603063838725SMat Martineau 
603163838725SMat Martineau 	return err;
6032d2a7ac5dSMat Martineau }
6033d2a7ac5dSMat Martineau 
6034d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6035d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6036d2a7ac5dSMat Martineau {
6037f80842a8SMat Martineau 	struct sk_buff *skb;
6038f80842a8SMat Martineau 
6039f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6040f80842a8SMat Martineau 
6041f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6042f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
60435e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6044f80842a8SMat Martineau 		return;
6045f80842a8SMat Martineau 	}
6046f80842a8SMat Martineau 
6047f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6048f80842a8SMat Martineau 
6049f80842a8SMat Martineau 	if (skb == NULL) {
6050f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6051f80842a8SMat Martineau 		       control->reqseq);
6052f80842a8SMat Martineau 		return;
6053f80842a8SMat Martineau 	}
6054f80842a8SMat Martineau 
6055a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6056f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
60575e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6058f80842a8SMat Martineau 		return;
6059f80842a8SMat Martineau 	}
6060f80842a8SMat Martineau 
6061f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6062f80842a8SMat Martineau 
6063f80842a8SMat Martineau 	if (control->poll) {
6064f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6065f80842a8SMat Martineau 
6066f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6067f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6068f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6069f80842a8SMat Martineau 
6070f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6071f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6072f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6073f80842a8SMat Martineau 		}
6074f80842a8SMat Martineau 	} else {
6075f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6076f80842a8SMat Martineau 
6077f80842a8SMat Martineau 		if (control->final) {
6078f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6079f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6080f80842a8SMat Martineau 						&chan->conn_state))
6081f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6082f80842a8SMat Martineau 		} else {
6083f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6084f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6085f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6086f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6087f80842a8SMat Martineau 			}
6088f80842a8SMat Martineau 		}
6089f80842a8SMat Martineau 	}
6090d2a7ac5dSMat Martineau }
6091d2a7ac5dSMat Martineau 
6092d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6093d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6094d2a7ac5dSMat Martineau {
6095fcd289dfSMat Martineau 	struct sk_buff *skb;
6096fcd289dfSMat Martineau 
6097fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6098fcd289dfSMat Martineau 
6099fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6100fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61015e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6102fcd289dfSMat Martineau 		return;
6103fcd289dfSMat Martineau 	}
6104fcd289dfSMat Martineau 
6105fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6106fcd289dfSMat Martineau 
6107fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6108a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6109fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61105e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6111fcd289dfSMat Martineau 		return;
6112fcd289dfSMat Martineau 	}
6113fcd289dfSMat Martineau 
6114fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6115fcd289dfSMat Martineau 
6116fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6117fcd289dfSMat Martineau 
6118fcd289dfSMat Martineau 	if (control->final) {
6119fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6120fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6121fcd289dfSMat Martineau 	} else {
6122fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6123fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6124fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6125fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6126fcd289dfSMat Martineau 	}
6127d2a7ac5dSMat Martineau }
6128d2a7ac5dSMat Martineau 
61294b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
61304b51dae9SMat Martineau {
61314b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
61324b51dae9SMat Martineau 
61334b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
61344b51dae9SMat Martineau 	       chan->expected_tx_seq);
61354b51dae9SMat Martineau 
61364b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
61374b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61384b51dae9SMat Martineau 		    chan->tx_win) {
61394b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
61404b51dae9SMat Martineau 			 * invalid packets.
61414b51dae9SMat Martineau 			 */
61424b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
61434b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
61444b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
61454b51dae9SMat Martineau 			} else {
61464b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
61474b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
61484b51dae9SMat Martineau 			}
61494b51dae9SMat Martineau 		}
61504b51dae9SMat Martineau 
61514b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
61524b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
61534b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
61544b51dae9SMat Martineau 		}
61554b51dae9SMat Martineau 
61564b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
61574b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
61584b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
61594b51dae9SMat Martineau 		}
61604b51dae9SMat Martineau 
61614b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
61624b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
61634b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
61644b51dae9SMat Martineau 		}
61654b51dae9SMat Martineau 	}
61664b51dae9SMat Martineau 
61674b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
61684b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61694b51dae9SMat Martineau 		    chan->tx_win) {
61704b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
61714b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
61724b51dae9SMat Martineau 		} else {
61734b51dae9SMat Martineau 			BT_DBG("Expected");
61744b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
61754b51dae9SMat Martineau 		}
61764b51dae9SMat Martineau 	}
61774b51dae9SMat Martineau 
61784b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
61792d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
61804b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
61814b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
61824b51dae9SMat Martineau 	}
61834b51dae9SMat Martineau 
61844b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
61854b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
61864b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
61874b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
61884b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
61894b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
61904b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
61914b51dae9SMat Martineau 		 * request.
61924b51dae9SMat Martineau 		 *
61934b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
61944b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
61954b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
61964b51dae9SMat Martineau 		 *
61974b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
61984b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
61994b51dae9SMat Martineau 		 * causes a disconnect.
62004b51dae9SMat Martineau 		 */
62014b51dae9SMat Martineau 
62024b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62034b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
62044b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
62054b51dae9SMat Martineau 		} else {
62064b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62074b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62084b51dae9SMat Martineau 		}
62094b51dae9SMat Martineau 	} else {
62104b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
62114b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
62124b51dae9SMat Martineau 	}
62134b51dae9SMat Martineau }
62144b51dae9SMat Martineau 
6215d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6216d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6217d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6218d2a7ac5dSMat Martineau {
6219d2a7ac5dSMat Martineau 	int err = 0;
6220941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6221d2a7ac5dSMat Martineau 
6222d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6223d2a7ac5dSMat Martineau 	       event);
6224d2a7ac5dSMat Martineau 
6225d2a7ac5dSMat Martineau 	switch (event) {
6226d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6227d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6228d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6229d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6230d2a7ac5dSMat Martineau 
6231d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6232d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6233d2a7ac5dSMat Martineau 				       control->txseq);
6234d2a7ac5dSMat Martineau 				break;
6235d2a7ac5dSMat Martineau 			}
6236d2a7ac5dSMat Martineau 
6237d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6238d2a7ac5dSMat Martineau 							   control->txseq);
6239d2a7ac5dSMat Martineau 
6240d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6241941247f9SPeter Senna Tschudin 			skb_in_use = true;
6242d2a7ac5dSMat Martineau 
6243d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6244d2a7ac5dSMat Martineau 			if (err)
6245d2a7ac5dSMat Martineau 				break;
6246d2a7ac5dSMat Martineau 
6247d2a7ac5dSMat Martineau 			if (control->final) {
6248d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6249d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6250d2a7ac5dSMat Martineau 					control->final = 0;
6251d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6252d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6253d2a7ac5dSMat Martineau 				}
6254d2a7ac5dSMat Martineau 			}
6255d2a7ac5dSMat Martineau 
6256d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6257d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6258d2a7ac5dSMat Martineau 			break;
6259d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6260d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6261d2a7ac5dSMat Martineau 
6262d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6263d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6264d2a7ac5dSMat Martineau 			 * when local busy is exited.
6265d2a7ac5dSMat Martineau 			 */
6266d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6267d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6268d2a7ac5dSMat Martineau 				       control->txseq);
6269d2a7ac5dSMat Martineau 				break;
6270d2a7ac5dSMat Martineau 			}
6271d2a7ac5dSMat Martineau 
6272d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6273d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6274d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6275d2a7ac5dSMat Martineau 			 */
6276d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6277941247f9SPeter Senna Tschudin 			skb_in_use = true;
6278d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6279d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6280d2a7ac5dSMat Martineau 
6281d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6282d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6283d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6284d2a7ac5dSMat Martineau 
6285d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6286d2a7ac5dSMat Martineau 			break;
6287d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6288d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6289d2a7ac5dSMat Martineau 			break;
6290d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6291d2a7ac5dSMat Martineau 			break;
6292d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6293d2a7ac5dSMat Martineau 		default:
62945e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6295d2a7ac5dSMat Martineau 			break;
6296d2a7ac5dSMat Martineau 		}
6297d2a7ac5dSMat Martineau 		break;
6298d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6299d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6300d2a7ac5dSMat Martineau 		if (control->final) {
6301d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6302d2a7ac5dSMat Martineau 
6303e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6304e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6305d2a7ac5dSMat Martineau 				control->final = 0;
6306d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6307d2a7ac5dSMat Martineau 			}
6308d2a7ac5dSMat Martineau 
6309d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6310d2a7ac5dSMat Martineau 		} else if (control->poll) {
6311d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6312d2a7ac5dSMat Martineau 		} else {
6313d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6314d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6315d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6316d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6317d2a7ac5dSMat Martineau 
6318d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6319d2a7ac5dSMat Martineau 		}
6320d2a7ac5dSMat Martineau 		break;
6321d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6322d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6323d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6324d2a7ac5dSMat Martineau 		if (control && control->poll) {
6325d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6326d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6327d2a7ac5dSMat Martineau 		}
6328d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6329d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6330d2a7ac5dSMat Martineau 		break;
6331d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6332d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6333d2a7ac5dSMat Martineau 		break;
6334d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6335d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6336d2a7ac5dSMat Martineau 		break;
6337d2a7ac5dSMat Martineau 	default:
6338d2a7ac5dSMat Martineau 		break;
6339d2a7ac5dSMat Martineau 	}
6340d2a7ac5dSMat Martineau 
6341d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6342d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6343d2a7ac5dSMat Martineau 		kfree_skb(skb);
6344d2a7ac5dSMat Martineau 	}
6345d2a7ac5dSMat Martineau 
6346d2a7ac5dSMat Martineau 	return err;
6347d2a7ac5dSMat Martineau }
6348d2a7ac5dSMat Martineau 
6349d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6350d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6351d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6352d2a7ac5dSMat Martineau {
6353d2a7ac5dSMat Martineau 	int err = 0;
6354d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6355941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6356d2a7ac5dSMat Martineau 
6357d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6358d2a7ac5dSMat Martineau 	       event);
6359d2a7ac5dSMat Martineau 
6360d2a7ac5dSMat Martineau 	switch (event) {
6361d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6362d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6363d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6364d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6365d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6366d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6367941247f9SPeter Senna Tschudin 			skb_in_use = true;
6368d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6369d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6370d2a7ac5dSMat Martineau 
6371d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6372d2a7ac5dSMat Martineau 			break;
6373d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6374d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6375d2a7ac5dSMat Martineau 
6376d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6377d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6378941247f9SPeter Senna Tschudin 			skb_in_use = true;
6379d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6380d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6381d2a7ac5dSMat Martineau 
6382d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6383d2a7ac5dSMat Martineau 			if (err)
6384d2a7ac5dSMat Martineau 				break;
6385d2a7ac5dSMat Martineau 
6386d2a7ac5dSMat Martineau 			break;
6387d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6388d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6389d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6390d2a7ac5dSMat Martineau 			 * the missing frames.
6391d2a7ac5dSMat Martineau 			 */
6392d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6393941247f9SPeter Senna Tschudin 			skb_in_use = true;
6394d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6395d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6396d2a7ac5dSMat Martineau 
6397d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6398d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6399d2a7ac5dSMat Martineau 			break;
6400d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6401d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6402d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6403d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6404d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6405d2a7ac5dSMat Martineau 			 */
6406d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6407941247f9SPeter Senna Tschudin 			skb_in_use = true;
6408d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6409d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6410d2a7ac5dSMat Martineau 
6411d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6412d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6413d2a7ac5dSMat Martineau 			break;
6414d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6415d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6416d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6417d2a7ac5dSMat Martineau 			break;
6418d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6419d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6420d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6421d2a7ac5dSMat Martineau 			 */
6422d2a7ac5dSMat Martineau 			break;
6423d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6424d2a7ac5dSMat Martineau 			break;
6425d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6426d2a7ac5dSMat Martineau 		default:
64275e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6428d2a7ac5dSMat Martineau 			break;
6429d2a7ac5dSMat Martineau 		}
6430d2a7ac5dSMat Martineau 		break;
6431d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6432d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6433d2a7ac5dSMat Martineau 		if (control->final) {
6434d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6435d2a7ac5dSMat Martineau 
6436d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6437d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6438d2a7ac5dSMat Martineau 				control->final = 0;
6439d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6440d2a7ac5dSMat Martineau 			}
6441d2a7ac5dSMat Martineau 
6442d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6443d2a7ac5dSMat Martineau 		} else if (control->poll) {
6444d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6445d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6446d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6447d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6448d2a7ac5dSMat Martineau 			}
6449d2a7ac5dSMat Martineau 
6450d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6451d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6452d2a7ac5dSMat Martineau 		} else {
6453d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6454d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6455d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6456d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6457d2a7ac5dSMat Martineau 
6458d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6459d2a7ac5dSMat Martineau 		}
6460d2a7ac5dSMat Martineau 		break;
6461d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6462d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6463d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6464d2a7ac5dSMat Martineau 		if (control->poll) {
6465d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6466d2a7ac5dSMat Martineau 		} else {
6467d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6468d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6469d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6470d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6471d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6472d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6473d2a7ac5dSMat Martineau 		}
6474d2a7ac5dSMat Martineau 
6475d2a7ac5dSMat Martineau 		break;
6476d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6477d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6478d2a7ac5dSMat Martineau 		break;
6479d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6480d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6481d2a7ac5dSMat Martineau 		break;
6482d2a7ac5dSMat Martineau 	}
6483d2a7ac5dSMat Martineau 
6484d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6485d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6486d2a7ac5dSMat Martineau 		kfree_skb(skb);
6487d2a7ac5dSMat Martineau 	}
6488d2a7ac5dSMat Martineau 
6489d2a7ac5dSMat Martineau 	return err;
6490d2a7ac5dSMat Martineau }
6491d2a7ac5dSMat Martineau 
649232b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
649332b32735SMat Martineau {
649432b32735SMat Martineau 	BT_DBG("chan %p", chan);
649532b32735SMat Martineau 
649632b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
649732b32735SMat Martineau 
649832b32735SMat Martineau 	if (chan->hs_hcon)
649932b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
650032b32735SMat Martineau 	else
650132b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
650232b32735SMat Martineau 
650332b32735SMat Martineau 	return l2cap_resegment(chan);
650432b32735SMat Martineau }
650532b32735SMat Martineau 
650632b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
650732b32735SMat Martineau 				 struct l2cap_ctrl *control,
650832b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
650932b32735SMat Martineau {
651032b32735SMat Martineau 	int err;
651132b32735SMat Martineau 
651232b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
651332b32735SMat Martineau 	       event);
651432b32735SMat Martineau 
651532b32735SMat Martineau 	if (!control->poll)
651632b32735SMat Martineau 		return -EPROTO;
651732b32735SMat Martineau 
651832b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
651932b32735SMat Martineau 
652032b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
652132b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
652232b32735SMat Martineau 	else
652332b32735SMat Martineau 		chan->tx_send_head = NULL;
652432b32735SMat Martineau 
652532b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
652632b32735SMat Martineau 	 * by the receiver.
652732b32735SMat Martineau 	 */
652832b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
652932b32735SMat Martineau 	chan->unacked_frames = 0;
653032b32735SMat Martineau 
653132b32735SMat Martineau 	err = l2cap_finish_move(chan);
653232b32735SMat Martineau 	if (err)
653332b32735SMat Martineau 		return err;
653432b32735SMat Martineau 
653532b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
653632b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
653732b32735SMat Martineau 
653832b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
653932b32735SMat Martineau 		return -EPROTO;
654032b32735SMat Martineau 
654132b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
654232b32735SMat Martineau }
654332b32735SMat Martineau 
654432b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
654532b32735SMat Martineau 				 struct l2cap_ctrl *control,
654632b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
654732b32735SMat Martineau {
654832b32735SMat Martineau 	int err;
654932b32735SMat Martineau 
655032b32735SMat Martineau 	if (!control->final)
655132b32735SMat Martineau 		return -EPROTO;
655232b32735SMat Martineau 
655332b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
655432b32735SMat Martineau 
655532b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
655632b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
655732b32735SMat Martineau 
655832b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
655932b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
656032b32735SMat Martineau 	else
656132b32735SMat Martineau 		chan->tx_send_head = NULL;
656232b32735SMat Martineau 
656332b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
656432b32735SMat Martineau 	 * by the receiver.
656532b32735SMat Martineau 	 */
656632b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
656732b32735SMat Martineau 	chan->unacked_frames = 0;
656832b32735SMat Martineau 
656932b32735SMat Martineau 	if (chan->hs_hcon)
657032b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
657132b32735SMat Martineau 	else
657232b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
657332b32735SMat Martineau 
657432b32735SMat Martineau 	err = l2cap_resegment(chan);
657532b32735SMat Martineau 
657632b32735SMat Martineau 	if (!err)
657732b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
657832b32735SMat Martineau 
657932b32735SMat Martineau 	return err;
658032b32735SMat Martineau }
658132b32735SMat Martineau 
6582d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6583d2a7ac5dSMat Martineau {
6584d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6585d2a7ac5dSMat Martineau 	u16 unacked;
6586d2a7ac5dSMat Martineau 
6587d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6588d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6589d2a7ac5dSMat Martineau }
6590d2a7ac5dSMat Martineau 
6591cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6592cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
65930a708f8fSGustavo F. Padovan {
6594d2a7ac5dSMat Martineau 	int err = 0;
6595d2a7ac5dSMat Martineau 
6596d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6597d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6598d2a7ac5dSMat Martineau 
6599d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6600d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6601d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6602d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6603d2a7ac5dSMat Martineau 			break;
6604d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6605d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6606d2a7ac5dSMat Martineau 						       event);
6607d2a7ac5dSMat Martineau 			break;
660832b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
660932b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
661032b32735SMat Martineau 			break;
661132b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
661232b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
661332b32735SMat Martineau 			break;
6614d2a7ac5dSMat Martineau 		default:
6615d2a7ac5dSMat Martineau 			/* shut it down */
6616d2a7ac5dSMat Martineau 			break;
6617d2a7ac5dSMat Martineau 		}
6618d2a7ac5dSMat Martineau 	} else {
6619d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6620d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6621d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
66225e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6623d2a7ac5dSMat Martineau 	}
6624d2a7ac5dSMat Martineau 
6625d2a7ac5dSMat Martineau 	return err;
6626cec8ab6eSMat Martineau }
6627cec8ab6eSMat Martineau 
6628cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6629cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6630cec8ab6eSMat Martineau {
66314b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
66324b51dae9SMat Martineau 	       chan->rx_state);
66334b51dae9SMat Martineau 
66344b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
66354b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
66364b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
66374b51dae9SMat Martineau 
66384b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
66394b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
66404b51dae9SMat Martineau 
66414b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
66424b51dae9SMat Martineau 
66434b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
66444b51dae9SMat Martineau 	} else {
66454b51dae9SMat Martineau 		if (chan->sdu) {
66464b51dae9SMat Martineau 			kfree_skb(chan->sdu);
66474b51dae9SMat Martineau 			chan->sdu = NULL;
66484b51dae9SMat Martineau 		}
66494b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
66504b51dae9SMat Martineau 		chan->sdu_len = 0;
66514b51dae9SMat Martineau 
66524b51dae9SMat Martineau 		if (skb) {
66534b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
66544b51dae9SMat Martineau 			kfree_skb(skb);
66554b51dae9SMat Martineau 		}
66564b51dae9SMat Martineau 	}
66574b51dae9SMat Martineau 
66584b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
66594b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
66604b51dae9SMat Martineau 
66619a544210SPrasanna Karthik 	return 0;
6662cec8ab6eSMat Martineau }
6663cec8ab6eSMat Martineau 
6664cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6665cec8ab6eSMat Martineau {
6666a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
6667cec8ab6eSMat Martineau 	u16 len;
6668cec8ab6eSMat Martineau 	u8 event;
66690a708f8fSGustavo F. Padovan 
6670b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6671b76bbd66SMat Martineau 
66720a708f8fSGustavo F. Padovan 	len = skb->len;
66730a708f8fSGustavo F. Padovan 
66740a708f8fSGustavo F. Padovan 	/*
66750a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
66760a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6677cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
66780a708f8fSGustavo F. Padovan 	 */
667947d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
66800a708f8fSGustavo F. Padovan 		goto drop;
66810a708f8fSGustavo F. Padovan 
6682cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
668303a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
66840a708f8fSGustavo F. Padovan 
668547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
668603a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
66870a708f8fSGustavo F. Padovan 
668847d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
66895e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
66900a708f8fSGustavo F. Padovan 		goto drop;
66910a708f8fSGustavo F. Padovan 	}
66920a708f8fSGustavo F. Padovan 
6693dbb50887SDaniel Borkmann 	if ((chan->mode == L2CAP_MODE_ERTM ||
6694dbb50887SDaniel Borkmann 	     chan->mode == L2CAP_MODE_STREAMING) && sk_filter(chan->data, skb))
6695dbb50887SDaniel Borkmann 		goto drop;
6696dbb50887SDaniel Borkmann 
6697cec8ab6eSMat Martineau 	if (!control->sframe) {
6698cec8ab6eSMat Martineau 		int err;
66990a708f8fSGustavo F. Padovan 
6700cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6701cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6702cec8ab6eSMat Martineau 		       control->txseq);
6703836be934SAndrei Emeltchenko 
6704cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6705cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6706cec8ab6eSMat Martineau 		 */
6707cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
67080a708f8fSGustavo F. Padovan 			goto drop;
67090a708f8fSGustavo F. Padovan 
6710cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6711cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6712cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
67130a708f8fSGustavo F. Padovan 		} else {
6714cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6715cec8ab6eSMat Martineau 		}
6716cec8ab6eSMat Martineau 
6717cec8ab6eSMat Martineau 		if (err)
67185e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6719cec8ab6eSMat Martineau 	} else {
6720cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6721cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6722cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6723cec8ab6eSMat Martineau 		};
6724cec8ab6eSMat Martineau 
6725cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6726cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6727cec8ab6eSMat Martineau 			goto drop;
6728cec8ab6eSMat Martineau 
6729cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6730cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6731cec8ab6eSMat Martineau 		       control->super);
6732cec8ab6eSMat Martineau 
67330a708f8fSGustavo F. Padovan 		if (len != 0) {
67341bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
67355e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67360a708f8fSGustavo F. Padovan 			goto drop;
67370a708f8fSGustavo F. Padovan 		}
67380a708f8fSGustavo F. Padovan 
6739cec8ab6eSMat Martineau 		/* Validate F and P bits */
6740cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6741cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6742cec8ab6eSMat Martineau 			goto drop;
6743cec8ab6eSMat Martineau 
6744cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6745cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
67465e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67470a708f8fSGustavo F. Padovan 	}
67480a708f8fSGustavo F. Padovan 
67490a708f8fSGustavo F. Padovan 	return 0;
67500a708f8fSGustavo F. Padovan 
67510a708f8fSGustavo F. Padovan drop:
67520a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67530a708f8fSGustavo F. Padovan 	return 0;
67540a708f8fSGustavo F. Padovan }
67550a708f8fSGustavo F. Padovan 
6756b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6757b1c325c2SJohan Hedberg {
6758b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6759b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6760b1c325c2SJohan Hedberg 	u16 return_credits;
6761b1c325c2SJohan Hedberg 
676296cd8eaaSLuiz Augusto von Dentz 	return_credits = ((chan->imtu / chan->mps) + 1) - chan->rx_credits;
6763b1c325c2SJohan Hedberg 
676496cd8eaaSLuiz Augusto von Dentz 	if (!return_credits)
676596cd8eaaSLuiz Augusto von Dentz 		return;
6766b1c325c2SJohan Hedberg 
6767b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6768b1c325c2SJohan Hedberg 
6769b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6770b1c325c2SJohan Hedberg 
6771b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6772b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6773b1c325c2SJohan Hedberg 
6774b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6775b1c325c2SJohan Hedberg 
6776b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6777b1c325c2SJohan Hedberg }
6778b1c325c2SJohan Hedberg 
677996cd8eaaSLuiz Augusto von Dentz static int l2cap_le_recv(struct l2cap_chan *chan, struct sk_buff *skb)
678096cd8eaaSLuiz Augusto von Dentz {
678196cd8eaaSLuiz Augusto von Dentz 	int err;
678296cd8eaaSLuiz Augusto von Dentz 
678396cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
678496cd8eaaSLuiz Augusto von Dentz 
678596cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
678696cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
678796cd8eaaSLuiz Augusto von Dentz 
678896cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
678996cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
679096cd8eaaSLuiz Augusto von Dentz 
679196cd8eaaSLuiz Augusto von Dentz 	return err;
679296cd8eaaSLuiz Augusto von Dentz }
679396cd8eaaSLuiz Augusto von Dentz 
6794fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6795fad5fc89SJohan Hedberg {
6796aac23bf6SJohan Hedberg 	int err;
6797fad5fc89SJohan Hedberg 
6798aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6799aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6800dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
6801fad5fc89SJohan Hedberg 		return -ENOBUFS;
6802aac23bf6SJohan Hedberg 	}
6803aac23bf6SJohan Hedberg 
6804aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6805aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6806aac23bf6SJohan Hedberg 		return -ENOBUFS;
6807aac23bf6SJohan Hedberg 	}
6808fad5fc89SJohan Hedberg 
6809fad5fc89SJohan Hedberg 	chan->rx_credits--;
6810fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6811fad5fc89SJohan Hedberg 
681296cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
681396cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
681496cd8eaaSLuiz Augusto von Dentz 	 */
681596cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
6816fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
6817fad5fc89SJohan Hedberg 
6818aac23bf6SJohan Hedberg 	err = 0;
6819aac23bf6SJohan Hedberg 
6820aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6821aac23bf6SJohan Hedberg 		u16 sdu_len;
6822aac23bf6SJohan Hedberg 
6823aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6824aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6825aac23bf6SJohan Hedberg 
6826aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6827aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6828aac23bf6SJohan Hedberg 
6829aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6830aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6831aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6832aac23bf6SJohan Hedberg 			goto failed;
6833aac23bf6SJohan Hedberg 		}
6834aac23bf6SJohan Hedberg 
6835aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6836aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6837aac23bf6SJohan Hedberg 			err = -EINVAL;
6838aac23bf6SJohan Hedberg 			goto failed;
6839aac23bf6SJohan Hedberg 		}
6840aac23bf6SJohan Hedberg 
6841aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
684296cd8eaaSLuiz Augusto von Dentz 			return l2cap_le_recv(chan, skb);
6843aac23bf6SJohan Hedberg 
6844aac23bf6SJohan Hedberg 		chan->sdu = skb;
6845aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6846aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6847aac23bf6SJohan Hedberg 
6848a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
6849a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
6850a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
6851a5c3021bSLuiz Augusto von Dentz 
6852a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
6853a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
6854a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
6855a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
6856a5c3021bSLuiz Augusto von Dentz 		}
6857a5c3021bSLuiz Augusto von Dentz 
6858aac23bf6SJohan Hedberg 		return 0;
6859aac23bf6SJohan Hedberg 	}
6860aac23bf6SJohan Hedberg 
6861aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6862aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6863aac23bf6SJohan Hedberg 
6864aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6865aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6866aac23bf6SJohan Hedberg 		err = -EINVAL;
6867aac23bf6SJohan Hedberg 		goto failed;
6868aac23bf6SJohan Hedberg 	}
6869aac23bf6SJohan Hedberg 
6870aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6871aac23bf6SJohan Hedberg 	skb = NULL;
6872aac23bf6SJohan Hedberg 
6873aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
687496cd8eaaSLuiz Augusto von Dentz 		err = l2cap_le_recv(chan, chan->sdu);
6875aac23bf6SJohan Hedberg 		if (!err) {
6876aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6877aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6878aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6879aac23bf6SJohan Hedberg 		}
6880aac23bf6SJohan Hedberg 	}
6881aac23bf6SJohan Hedberg 
6882aac23bf6SJohan Hedberg failed:
6883aac23bf6SJohan Hedberg 	if (err) {
6884aac23bf6SJohan Hedberg 		kfree_skb(skb);
6885aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6886aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6887aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6888aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6889aac23bf6SJohan Hedberg 	}
6890aac23bf6SJohan Hedberg 
6891aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6892aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6893aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6894aac23bf6SJohan Hedberg 	 */
6895aac23bf6SJohan Hedberg 	return 0;
6896fad5fc89SJohan Hedberg }
6897fad5fc89SJohan Hedberg 
689813ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
689913ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
69000a708f8fSGustavo F. Padovan {
690148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
69020a708f8fSGustavo F. Padovan 
6903baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
690448454079SGustavo F. Padovan 	if (!chan) {
690597e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
690697e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
690797e8e89dSAndrei Emeltchenko 			if (!chan) {
690897e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
690913ca56e0SAndrei Emeltchenko 				return;
691097e8e89dSAndrei Emeltchenko 			}
691197e8e89dSAndrei Emeltchenko 
691297e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
691397e8e89dSAndrei Emeltchenko 		} else {
69140a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
69156be36555SAndrei Emeltchenko 			/* Drop packet and return */
69163379013bSDan Carpenter 			kfree_skb(skb);
691713ca56e0SAndrei Emeltchenko 			return;
69180a708f8fSGustavo F. Padovan 		}
691997e8e89dSAndrei Emeltchenko 	}
69200a708f8fSGustavo F. Padovan 
692149208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
69220a708f8fSGustavo F. Padovan 
6923315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
6924315917e0SJohan Hedberg 	 * procdure is done simply assume that the channel is supported
6925315917e0SJohan Hedberg 	 * and mark it as ready.
6926315917e0SJohan Hedberg 	 */
6927315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
6928315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
6929315917e0SJohan Hedberg 
693089bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
69310a708f8fSGustavo F. Padovan 		goto drop;
69320a708f8fSGustavo F. Padovan 
69330c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
693438319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
6935fad5fc89SJohan Hedberg 		if (l2cap_le_data_rcv(chan, skb) < 0)
6936fad5fc89SJohan Hedberg 			goto drop;
6937fad5fc89SJohan Hedberg 
6938fad5fc89SJohan Hedberg 		goto done;
6939fad5fc89SJohan Hedberg 
69400a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
69410a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
69420a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
69430a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
69440a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
69450a708f8fSGustavo F. Padovan 
69462c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
69472c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
69480a708f8fSGustavo F. Padovan 			goto drop;
69492c96e03dSSzymon Janc 		}
69500a708f8fSGustavo F. Padovan 
695180b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
69520a708f8fSGustavo F. Padovan 			goto done;
69530a708f8fSGustavo F. Padovan 		break;
69540a708f8fSGustavo F. Padovan 
69550a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
69560a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6957cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
69580a708f8fSGustavo F. Padovan 		goto done;
69590a708f8fSGustavo F. Padovan 
69600a708f8fSGustavo F. Padovan 	default:
69610c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
69620a708f8fSGustavo F. Padovan 		break;
69630a708f8fSGustavo F. Padovan 	}
69640a708f8fSGustavo F. Padovan 
69650a708f8fSGustavo F. Padovan drop:
69660a708f8fSGustavo F. Padovan 	kfree_skb(skb);
69670a708f8fSGustavo F. Padovan 
69680a708f8fSGustavo F. Padovan done:
69696be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
69700a708f8fSGustavo F. Padovan }
69710a708f8fSGustavo F. Padovan 
697284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
697384104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
69740a708f8fSGustavo F. Padovan {
6975ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
697623691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
69770a708f8fSGustavo F. Padovan 
6978ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
6979a24cce14SJohan Hedberg 		goto free_skb;
6980ae4fd2d3SMarcel Holtmann 
6981bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6982bf20fd4eSJohan Hedberg 					ACL_LINK);
698323691d75SGustavo F. Padovan 	if (!chan)
6984a24cce14SJohan Hedberg 		goto free_skb;
69850a708f8fSGustavo F. Padovan 
69865b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
69870a708f8fSGustavo F. Padovan 
698889bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
69890a708f8fSGustavo F. Padovan 		goto drop;
69900a708f8fSGustavo F. Padovan 
6991e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
69920a708f8fSGustavo F. Padovan 		goto drop;
69930a708f8fSGustavo F. Padovan 
69942edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
6995a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
6996a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
69972edf870dSMarcel Holtmann 
6998a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
6999a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
700084104b24SAndrei Emeltchenko 		return;
7001a24cce14SJohan Hedberg 	}
70020a708f8fSGustavo F. Padovan 
70030a708f8fSGustavo F. Padovan drop:
7004a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
7005a24cce14SJohan Hedberg free_skb:
70060a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70070a708f8fSGustavo F. Padovan }
70080a708f8fSGustavo F. Padovan 
70090a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
70100a708f8fSGustavo F. Padovan {
70110a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
701261a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
70130a708f8fSGustavo F. Padovan 	u16 cid, len;
70140a708f8fSGustavo F. Padovan 	__le16 psm;
70150a708f8fSGustavo F. Padovan 
701661a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
701761a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
701861a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
701961a939c6SJohan Hedberg 		return;
702061a939c6SJohan Hedberg 	}
702161a939c6SJohan Hedberg 
70220a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
70230a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
70240a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
70250a708f8fSGustavo F. Padovan 
70260a708f8fSGustavo F. Padovan 	if (len != skb->len) {
70270a708f8fSGustavo F. Padovan 		kfree_skb(skb);
70280a708f8fSGustavo F. Padovan 		return;
70290a708f8fSGustavo F. Padovan 	}
70300a708f8fSGustavo F. Padovan 
70319e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
70329e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
70339e1d7e15SJohan Hedberg 	 */
70349e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
7035dcc36c16SJohan Hedberg 	    hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
7036a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
7037e493150eSJohan Hedberg 		kfree_skb(skb);
7038e493150eSJohan Hedberg 		return;
7039e493150eSJohan Hedberg 	}
7040e493150eSJohan Hedberg 
70410a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
70420a708f8fSGustavo F. Padovan 
70430a708f8fSGustavo F. Padovan 	switch (cid) {
70440a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
70450a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
70460a708f8fSGustavo F. Padovan 		break;
70470a708f8fSGustavo F. Padovan 
70480a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7049097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
70500181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
70510a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
70520a708f8fSGustavo F. Padovan 		break;
70530a708f8fSGustavo F. Padovan 
7054a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7055a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7056a2877629SMarcel Holtmann 		break;
7057a2877629SMarcel Holtmann 
70580a708f8fSGustavo F. Padovan 	default:
70590a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
70600a708f8fSGustavo F. Padovan 		break;
70610a708f8fSGustavo F. Padovan 	}
70620a708f8fSGustavo F. Padovan }
70630a708f8fSGustavo F. Padovan 
706461a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
706561a939c6SJohan Hedberg {
706661a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
706761a939c6SJohan Hedberg 					       pending_rx_work);
706861a939c6SJohan Hedberg 	struct sk_buff *skb;
706961a939c6SJohan Hedberg 
707061a939c6SJohan Hedberg 	BT_DBG("");
707161a939c6SJohan Hedberg 
707261a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
707361a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
707461a939c6SJohan Hedberg }
707561a939c6SJohan Hedberg 
7076162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
7077162b49e7SJohan Hedberg {
7078162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
7079162b49e7SJohan Hedberg 	struct hci_chan *hchan;
7080162b49e7SJohan Hedberg 
7081162b49e7SJohan Hedberg 	if (conn)
7082162b49e7SJohan Hedberg 		return conn;
7083162b49e7SJohan Hedberg 
7084162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
7085162b49e7SJohan Hedberg 	if (!hchan)
7086162b49e7SJohan Hedberg 		return NULL;
7087162b49e7SJohan Hedberg 
708827f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
7089162b49e7SJohan Hedberg 	if (!conn) {
7090162b49e7SJohan Hedberg 		hci_chan_del(hchan);
7091162b49e7SJohan Hedberg 		return NULL;
7092162b49e7SJohan Hedberg 	}
7093162b49e7SJohan Hedberg 
7094162b49e7SJohan Hedberg 	kref_init(&conn->ref);
7095162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
709651bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
7097162b49e7SJohan Hedberg 	conn->hchan = hchan;
7098162b49e7SJohan Hedberg 
7099162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
7100162b49e7SJohan Hedberg 
7101162b49e7SJohan Hedberg 	switch (hcon->type) {
7102162b49e7SJohan Hedberg 	case LE_LINK:
7103162b49e7SJohan Hedberg 		if (hcon->hdev->le_mtu) {
7104162b49e7SJohan Hedberg 			conn->mtu = hcon->hdev->le_mtu;
7105162b49e7SJohan Hedberg 			break;
7106162b49e7SJohan Hedberg 		}
7107162b49e7SJohan Hedberg 		/* fall through */
7108162b49e7SJohan Hedberg 	default:
7109162b49e7SJohan Hedberg 		conn->mtu = hcon->hdev->acl_mtu;
7110162b49e7SJohan Hedberg 		break;
7111162b49e7SJohan Hedberg 	}
7112162b49e7SJohan Hedberg 
7113162b49e7SJohan Hedberg 	conn->feat_mask = 0;
7114162b49e7SJohan Hedberg 
71150bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
71160bd49fc7SJohan Hedberg 
71170bd49fc7SJohan Hedberg 	if (hcon->type == ACL_LINK &&
7118d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
71190bd49fc7SJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_A2MP;
7120162b49e7SJohan Hedberg 
7121d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
7122f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
7123b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
7124b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
7125b5ae344dSJohan Hedberg 
71265a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
7127162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
7128162b49e7SJohan Hedberg 
7129162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
7130162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
7131162b49e7SJohan Hedberg 
7132162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
7133162b49e7SJohan Hedberg 
713461a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
713561a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
7136f3d82d0cSJohan Hedberg 	INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr);
713761a939c6SJohan Hedberg 
7138162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
7139162b49e7SJohan Hedberg 
7140162b49e7SJohan Hedberg 	return conn;
7141162b49e7SJohan Hedberg }
7142162b49e7SJohan Hedberg 
7143162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) {
7144162b49e7SJohan Hedberg 	if (!psm)
7145162b49e7SJohan Hedberg 		return false;
7146162b49e7SJohan Hedberg 
7147162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
7148162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
7149162b49e7SJohan Hedberg 
7150162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
7151162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
7152162b49e7SJohan Hedberg }
7153162b49e7SJohan Hedberg 
7154162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7155162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
7156162b49e7SJohan Hedberg {
7157162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
7158162b49e7SJohan Hedberg 	struct hci_conn *hcon;
7159162b49e7SJohan Hedberg 	struct hci_dev *hdev;
7160162b49e7SJohan Hedberg 	int err;
7161162b49e7SJohan Hedberg 
7162162b49e7SJohan Hedberg 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
7163162b49e7SJohan Hedberg 	       dst_type, __le16_to_cpu(psm));
7164162b49e7SJohan Hedberg 
716539385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
7166162b49e7SJohan Hedberg 	if (!hdev)
7167162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
7168162b49e7SJohan Hedberg 
7169162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
7170162b49e7SJohan Hedberg 
7171162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
7172162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
7173162b49e7SJohan Hedberg 		err = -EINVAL;
7174162b49e7SJohan Hedberg 		goto done;
7175162b49e7SJohan Hedberg 	}
7176162b49e7SJohan Hedberg 
717721626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
717821626e62SJohan Hedberg 		err = -EINVAL;
717921626e62SJohan Hedberg 		goto done;
718021626e62SJohan Hedberg 	}
718121626e62SJohan Hedberg 
718221626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
7183162b49e7SJohan Hedberg 		err = -EINVAL;
7184162b49e7SJohan Hedberg 		goto done;
7185162b49e7SJohan Hedberg 	}
7186162b49e7SJohan Hedberg 
7187162b49e7SJohan Hedberg 	switch (chan->mode) {
7188162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
7189162b49e7SJohan Hedberg 		break;
7190162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
7191162b49e7SJohan Hedberg 		break;
7192162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
7193162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
7194162b49e7SJohan Hedberg 		if (!disable_ertm)
7195162b49e7SJohan Hedberg 			break;
7196162b49e7SJohan Hedberg 		/* fall through */
7197162b49e7SJohan Hedberg 	default:
7198beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
7199162b49e7SJohan Hedberg 		goto done;
7200162b49e7SJohan Hedberg 	}
7201162b49e7SJohan Hedberg 
7202162b49e7SJohan Hedberg 	switch (chan->state) {
7203162b49e7SJohan Hedberg 	case BT_CONNECT:
7204162b49e7SJohan Hedberg 	case BT_CONNECT2:
7205162b49e7SJohan Hedberg 	case BT_CONFIG:
7206162b49e7SJohan Hedberg 		/* Already connecting */
7207162b49e7SJohan Hedberg 		err = 0;
7208162b49e7SJohan Hedberg 		goto done;
7209162b49e7SJohan Hedberg 
7210162b49e7SJohan Hedberg 	case BT_CONNECTED:
7211162b49e7SJohan Hedberg 		/* Already connected */
7212162b49e7SJohan Hedberg 		err = -EISCONN;
7213162b49e7SJohan Hedberg 		goto done;
7214162b49e7SJohan Hedberg 
7215162b49e7SJohan Hedberg 	case BT_OPEN:
7216162b49e7SJohan Hedberg 	case BT_BOUND:
7217162b49e7SJohan Hedberg 		/* Can connect */
7218162b49e7SJohan Hedberg 		break;
7219162b49e7SJohan Hedberg 
7220162b49e7SJohan Hedberg 	default:
7221162b49e7SJohan Hedberg 		err = -EBADFD;
7222162b49e7SJohan Hedberg 		goto done;
7223162b49e7SJohan Hedberg 	}
7224162b49e7SJohan Hedberg 
7225162b49e7SJohan Hedberg 	/* Set destination address and psm */
7226162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
7227162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
7228162b49e7SJohan Hedberg 
7229162b49e7SJohan Hedberg 	chan->psm = psm;
7230162b49e7SJohan Hedberg 	chan->dcid = cid;
7231162b49e7SJohan Hedberg 
72326f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
72336f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
72346f77d8c7SAndre Guedes 		 */
72356f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
72366f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
72376f77d8c7SAndre Guedes 		else
72386f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
72396f77d8c7SAndre Guedes 
7240d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
72410ad06aa6SJohan Hedberg 			hcon = hci_connect_le(hdev, dst, dst_type,
7242fa142220SJakub Pawlowski 					      chan->sec_level,
7243fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
7244082f2300SSzymon Janc 					      HCI_ROLE_SLAVE, NULL);
72450ad06aa6SJohan Hedberg 		else
72460ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
72470ad06aa6SJohan Hedberg 						   chan->sec_level,
72480ad06aa6SJohan Hedberg 						   HCI_LE_CONN_TIMEOUT);
72490ad06aa6SJohan Hedberg 
72506f77d8c7SAndre Guedes 	} else {
7251d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
725204a6c589SAndre Guedes 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type);
72536f77d8c7SAndre Guedes 	}
7254162b49e7SJohan Hedberg 
7255162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
7256162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
7257162b49e7SJohan Hedberg 		goto done;
7258162b49e7SJohan Hedberg 	}
7259162b49e7SJohan Hedberg 
7260162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7261162b49e7SJohan Hedberg 	if (!conn) {
7262162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7263162b49e7SJohan Hedberg 		err = -ENOMEM;
7264162b49e7SJohan Hedberg 		goto done;
7265162b49e7SJohan Hedberg 	}
7266162b49e7SJohan Hedberg 
726702e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
726802e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
726902e246aeSJohan Hedberg 
7270162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7271162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7272162b49e7SJohan Hedberg 		err = -EBUSY;
727302e246aeSJohan Hedberg 		goto chan_unlock;
7274162b49e7SJohan Hedberg 	}
7275162b49e7SJohan Hedberg 
7276162b49e7SJohan Hedberg 	/* Update source addr of the socket */
7277162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
7278a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
7279162b49e7SJohan Hedberg 
728002e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
7281162b49e7SJohan Hedberg 
7282162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
7283162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
7284162b49e7SJohan Hedberg 
7285162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
7286162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7287162b49e7SJohan Hedberg 
728861202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
728961202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
729061202e4dSJohan Hedberg 	 */
729161202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
729261202e4dSJohan Hedberg 	chan->sport = 0;
729361202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
729461202e4dSJohan Hedberg 
7295162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
7296162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7297162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
7298e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
7299162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
7300162b49e7SJohan Hedberg 		} else
7301162b49e7SJohan Hedberg 			l2cap_do_start(chan);
7302162b49e7SJohan Hedberg 	}
7303162b49e7SJohan Hedberg 
7304162b49e7SJohan Hedberg 	err = 0;
7305162b49e7SJohan Hedberg 
730602e246aeSJohan Hedberg chan_unlock:
7307162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
730802e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
730902e246aeSJohan Hedberg done:
7310162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
7311162b49e7SJohan Hedberg 	hci_dev_put(hdev);
7312162b49e7SJohan Hedberg 	return err;
7313162b49e7SJohan Hedberg }
73146b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7315162b49e7SJohan Hedberg 
73160a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
73170a708f8fSGustavo F. Padovan 
7318686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
73190a708f8fSGustavo F. Padovan {
73200a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
732123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
73220a708f8fSGustavo F. Padovan 
73236ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
73240a708f8fSGustavo F. Padovan 
73250a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
732623691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
732723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
732889bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
73290a708f8fSGustavo F. Padovan 			continue;
73300a708f8fSGustavo F. Padovan 
73317eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
73320a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
733343bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
73340a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
73350a708f8fSGustavo F. Padovan 			exact++;
73367eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
73370a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
733843bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
73390a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
73400a708f8fSGustavo F. Padovan 		}
73410a708f8fSGustavo F. Padovan 	}
734223691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
73430a708f8fSGustavo F. Padovan 
73440a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
73450a708f8fSGustavo F. Padovan }
73460a708f8fSGustavo F. Padovan 
7347e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
7348e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
7349e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
7350e760ec12SJohan Hedberg  */
7351e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
7352327a7191SJohan Hedberg 						  struct hci_conn *hcon)
7353e760ec12SJohan Hedberg {
7354327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
7355327a7191SJohan Hedberg 
7356e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
7357e760ec12SJohan Hedberg 
7358e760ec12SJohan Hedberg 	if (c)
7359e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
7360e760ec12SJohan Hedberg 	else
7361e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
7362e760ec12SJohan Hedberg 
7363e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
7364e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
7365e760ec12SJohan Hedberg 			continue;
7366e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
7367e760ec12SJohan Hedberg 			continue;
7368327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
7369e760ec12SJohan Hedberg 			continue;
7370327a7191SJohan Hedberg 		if (src_type != c->src_type)
737154a1b626SJohan Hedberg 			continue;
7372e760ec12SJohan Hedberg 
7373e760ec12SJohan Hedberg 		l2cap_chan_hold(c);
7374e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
7375e760ec12SJohan Hedberg 		return c;
7376e760ec12SJohan Hedberg 	}
7377e760ec12SJohan Hedberg 
7378e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
7379e760ec12SJohan Hedberg 
7380e760ec12SJohan Hedberg 	return NULL;
7381e760ec12SJohan Hedberg }
7382e760ec12SJohan Hedberg 
7383539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
73840a708f8fSGustavo F. Padovan {
7385e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
73860a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
7387e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
7388e760ec12SJohan Hedberg 	u8 dst_type;
73890a708f8fSGustavo F. Padovan 
7390539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7391539c496dSJohan Hedberg 		return;
7392539c496dSJohan Hedberg 
73936ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
73940a708f8fSGustavo F. Padovan 
7395dc0f5088SJohan Hedberg 	if (status) {
7396e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7397dc0f5088SJohan Hedberg 		return;
7398ba6fc317SAndrei Emeltchenko 	}
7399dc0f5088SJohan Hedberg 
7400dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7401dc0f5088SJohan Hedberg 	if (!conn)
7402dc0f5088SJohan Hedberg 		return;
7403dc0f5088SJohan Hedberg 
7404a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
7405e760ec12SJohan Hedberg 
7406e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
7407e760ec12SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
7408e760ec12SJohan Hedberg 		return;
7409e760ec12SJohan Hedberg 
7410e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
7411e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
7412e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
7413e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
7414e760ec12SJohan Hedberg 	 */
7415327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
7416e760ec12SJohan Hedberg 	while (pchan) {
7417e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
7418e760ec12SJohan Hedberg 
7419e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
7420e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
7421e760ec12SJohan Hedberg 			goto next;
7422e760ec12SJohan Hedberg 
7423e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
7424e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
7425e760ec12SJohan Hedberg 		if (chan) {
7426e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
7427e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
7428a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
7429e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
7430e760ec12SJohan Hedberg 
7431e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
7432e760ec12SJohan Hedberg 		}
7433e760ec12SJohan Hedberg 
7434e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
7435e760ec12SJohan Hedberg next:
7436327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
7437e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
7438e760ec12SJohan Hedberg 		pchan = next;
7439e760ec12SJohan Hedberg 	}
7440e760ec12SJohan Hedberg 
7441dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
74420a708f8fSGustavo F. Padovan }
74430a708f8fSGustavo F. Padovan 
7444686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
74450a708f8fSGustavo F. Padovan {
74460a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
74470a708f8fSGustavo F. Padovan 
74480a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
74490a708f8fSGustavo F. Padovan 
7450686ebf28SUlisses Furquim 	if (!conn)
74519f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
74520a708f8fSGustavo F. Padovan 	return conn->disc_reason;
74530a708f8fSGustavo F. Padovan }
74540a708f8fSGustavo F. Padovan 
74553a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
74560a708f8fSGustavo F. Padovan {
74573a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
74583a6d576bSJohan Hedberg 		return;
74593a6d576bSJohan Hedberg 
74600a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
74610a708f8fSGustavo F. Padovan 
7462e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
74630a708f8fSGustavo F. Padovan }
74640a708f8fSGustavo F. Padovan 
74654343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
74660a708f8fSGustavo F. Padovan {
7467715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
74680a708f8fSGustavo F. Padovan 		return;
74690a708f8fSGustavo F. Padovan 
74700a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
74714343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7472ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
74737d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
74747d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
74750f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
74760a708f8fSGustavo F. Padovan 	} else {
74774343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7478c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
74790a708f8fSGustavo F. Padovan 	}
74800a708f8fSGustavo F. Padovan }
74810a708f8fSGustavo F. Padovan 
7482354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
74830a708f8fSGustavo F. Padovan {
74840a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
748548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
74860a708f8fSGustavo F. Padovan 
74870a708f8fSGustavo F. Padovan 	if (!conn)
7488354fe804SJohan Hedberg 		return;
74890a708f8fSGustavo F. Padovan 
749089d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
74910a708f8fSGustavo F. Padovan 
74923df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
74930a708f8fSGustavo F. Padovan 
74943df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
74956be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
74960a708f8fSGustavo F. Padovan 
749789d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
749889d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7499f1cb9af5SVinicius Costa Gomes 
75002338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
750178eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
750278eb2f98SAndrei Emeltchenko 			continue;
750378eb2f98SAndrei Emeltchenko 		}
750478eb2f98SAndrei Emeltchenko 
7505191eb398SJohan Hedberg 		if (!status && encrypt)
7506f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
7507f1cb9af5SVinicius Costa Gomes 
750896eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
75096be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
75100a708f8fSGustavo F. Padovan 			continue;
75110a708f8fSGustavo F. Padovan 		}
75120a708f8fSGustavo F. Padovan 
751389bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
751489bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7515d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
75164343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
75176be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
75180a708f8fSGustavo F. Padovan 			continue;
75190a708f8fSGustavo F. Padovan 		}
75200a708f8fSGustavo F. Padovan 
752189bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
7522693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
752393c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
75246d3c15daSJohan Hedberg 			else
7525ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7526fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
7527fa37c1aaSJohan Hedberg 			   chan->mode != L2CAP_MODE_LE_FLOWCTL) {
75280a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7529df3c3931SJohan Hedberg 			__u16 res, stat;
75300a708f8fSGustavo F. Padovan 
7531693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
7532bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7533df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7534df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
75352dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7536df3c3931SJohan Hedberg 				} else {
7537acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7538df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7539df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7540df3c3931SJohan Hedberg 				}
75410a708f8fSGustavo F. Padovan 			} else {
7542acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7543ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7544df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7545df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
75460a708f8fSGustavo F. Padovan 			}
75470a708f8fSGustavo F. Padovan 
7548fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7549fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7550df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7551df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7552fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7553fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
75542d369359SMat Martineau 
75552d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
75562d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
75572d369359SMat Martineau 				char buf[128];
75582d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
75592d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
75602d369359SMat Martineau 					       L2CAP_CONF_REQ,
7561e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
75622d369359SMat Martineau 					       buf);
75632d369359SMat Martineau 				chan->num_conf_req++;
75642d369359SMat Martineau 			}
75650a708f8fSGustavo F. Padovan 		}
75660a708f8fSGustavo F. Padovan 
75676be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
75680a708f8fSGustavo F. Padovan 	}
75690a708f8fSGustavo F. Padovan 
75703df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
75710a708f8fSGustavo F. Padovan }
75720a708f8fSGustavo F. Padovan 
75739b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
75740a708f8fSGustavo F. Padovan {
75750a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7576d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
7577d73a0988SAndrei Emeltchenko 	int len;
75780a708f8fSGustavo F. Padovan 
75791d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
7580ca8bee5dSMarcel Holtmann 	if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
75811d13a254SAndrei Emeltchenko 		goto drop;
75820a708f8fSGustavo F. Padovan 
75830a708f8fSGustavo F. Padovan 	if (!conn)
7584baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
75850a708f8fSGustavo F. Padovan 
75860a708f8fSGustavo F. Padovan 	if (!conn)
75870a708f8fSGustavo F. Padovan 		goto drop;
75880a708f8fSGustavo F. Padovan 
75890a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
75900a708f8fSGustavo F. Padovan 
7591d73a0988SAndrei Emeltchenko 	switch (flags) {
7592d73a0988SAndrei Emeltchenko 	case ACL_START:
7593d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7594d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
75950a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
75960a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
75970a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
75980a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
75990a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
76000a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76010a708f8fSGustavo F. Padovan 		}
76020a708f8fSGustavo F. Padovan 
76030a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
76040a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
76050a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
76060a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76070a708f8fSGustavo F. Padovan 			goto drop;
76080a708f8fSGustavo F. Padovan 		}
76090a708f8fSGustavo F. Padovan 
76100a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
76110a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
76120a708f8fSGustavo F. Padovan 
76130a708f8fSGustavo F. Padovan 		if (len == skb->len) {
76140a708f8fSGustavo F. Padovan 			/* Complete frame received */
76150a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
76169b4c3336SArron Wang 			return;
76170a708f8fSGustavo F. Padovan 		}
76180a708f8fSGustavo F. Padovan 
76190a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
76200a708f8fSGustavo F. Padovan 
76210a708f8fSGustavo F. Padovan 		if (skb->len > len) {
76220a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
76230a708f8fSGustavo F. Padovan 			       skb->len, len);
76240a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76250a708f8fSGustavo F. Padovan 			goto drop;
76260a708f8fSGustavo F. Padovan 		}
76270a708f8fSGustavo F. Padovan 
76280a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
76298bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
76300a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
76310a708f8fSGustavo F. Padovan 			goto drop;
76320a708f8fSGustavo F. Padovan 
76330a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
76340a708f8fSGustavo F. Padovan 					  skb->len);
76350a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7636d73a0988SAndrei Emeltchenko 		break;
7637d73a0988SAndrei Emeltchenko 
7638d73a0988SAndrei Emeltchenko 	case ACL_CONT:
76390a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
76400a708f8fSGustavo F. Padovan 
76410a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
76420a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
76430a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76440a708f8fSGustavo F. Padovan 			goto drop;
76450a708f8fSGustavo F. Padovan 		}
76460a708f8fSGustavo F. Padovan 
76470a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
76480a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
76490a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
76500a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
76510a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
76520a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
76530a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
76540a708f8fSGustavo F. Padovan 			goto drop;
76550a708f8fSGustavo F. Padovan 		}
76560a708f8fSGustavo F. Padovan 
76570a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
76580a708f8fSGustavo F. Padovan 					  skb->len);
76590a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
76600a708f8fSGustavo F. Padovan 
76610a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7662c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7663c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7664c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7665c4e5bafaSJohan Hedberg 			 */
7666c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
76670a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7668c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
76690a708f8fSGustavo F. Padovan 		}
7670d73a0988SAndrei Emeltchenko 		break;
76710a708f8fSGustavo F. Padovan 	}
76720a708f8fSGustavo F. Padovan 
76730a708f8fSGustavo F. Padovan drop:
76740a708f8fSGustavo F. Padovan 	kfree_skb(skb);
76750a708f8fSGustavo F. Padovan }
76760a708f8fSGustavo F. Padovan 
7677354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
7678354fe804SJohan Hedberg 	.name		= "L2CAP",
7679539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
76803a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
7681354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
7682354fe804SJohan Hedberg };
7683354fe804SJohan Hedberg 
76840a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
76850a708f8fSGustavo F. Padovan {
768623691d75SGustavo F. Padovan 	struct l2cap_chan *c;
76870a708f8fSGustavo F. Padovan 
7688333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
76890a708f8fSGustavo F. Padovan 
769023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7691eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
7692eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
769389bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
769423691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
769523691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
76960a708f8fSGustavo F. Padovan 	}
76970a708f8fSGustavo F. Padovan 
7698333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
76990a708f8fSGustavo F. Padovan 
77000a708f8fSGustavo F. Padovan 	return 0;
77010a708f8fSGustavo F. Padovan }
77020a708f8fSGustavo F. Padovan 
77038e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
77040a708f8fSGustavo F. Padovan 
77050a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
77060a708f8fSGustavo F. Padovan 
770764274518SGustavo F. Padovan int __init l2cap_init(void)
77080a708f8fSGustavo F. Padovan {
77090a708f8fSGustavo F. Padovan 	int err;
77100a708f8fSGustavo F. Padovan 
7711bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
77120a708f8fSGustavo F. Padovan 	if (err < 0)
77130a708f8fSGustavo F. Padovan 		return err;
77140a708f8fSGustavo F. Padovan 
7715354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
7716354fe804SJohan Hedberg 
77171120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
77181120e4bfSMarcel Holtmann 		return 0;
77191120e4bfSMarcel Holtmann 
77202d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
77212d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
77220a708f8fSGustavo F. Padovan 
77230a708f8fSGustavo F. Padovan 	return 0;
77240a708f8fSGustavo F. Padovan }
77250a708f8fSGustavo F. Padovan 
772664274518SGustavo F. Padovan void l2cap_exit(void)
77270a708f8fSGustavo F. Padovan {
77280a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7729354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
7730bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
77310a708f8fSGustavo F. Padovan }
77320a708f8fSGustavo F. Padovan 
77330a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
77340a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7735