xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 3a9d54b1)
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;
484be5ca67SLuiz Augusto von Dentz bool enable_ecred;
490a708f8fSGustavo F. Padovan 
50547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
510a708f8fSGustavo F. Padovan 
52b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
53b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
540a708f8fSGustavo F. Padovan 
550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
560a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
584519de9aSGustavo F. Padovan 			   void *data);
59e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
610a708f8fSGustavo F. Padovan 
62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
63608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
64608bcc6dSMat Martineau 
65a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
664f1654e0SMarcel Holtmann {
67a250e048SJohan Hedberg 	if (link_type == LE_LINK) {
68a250e048SJohan Hedberg 		if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
694f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
704f1654e0SMarcel Holtmann 		else
714f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
724f1654e0SMarcel Holtmann 	}
734f1654e0SMarcel Holtmann 
744f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
754f1654e0SMarcel Holtmann }
764f1654e0SMarcel Holtmann 
77a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
78a250e048SJohan Hedberg {
79a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->src_type);
80a250e048SJohan Hedberg }
81a250e048SJohan Hedberg 
82a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
83a250e048SJohan Hedberg {
84a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->dst_type);
85a250e048SJohan Hedberg }
86a250e048SJohan Hedberg 
870a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8871ba0e56SGustavo F. Padovan 
892d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
902d792818SGustavo Padovan 						   u16 cid)
910a708f8fSGustavo F. Padovan {
923df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
93baa7e1faSGustavo F. Padovan 
943df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
953df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
963df91ea2SAndrei Emeltchenko 			return c;
970a708f8fSGustavo F. Padovan 	}
983df91ea2SAndrei Emeltchenko 	return NULL;
99baa7e1faSGustavo F. Padovan }
1000a708f8fSGustavo F. Padovan 
1012d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1022d792818SGustavo Padovan 						   u16 cid)
1030a708f8fSGustavo F. Padovan {
1043df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
105baa7e1faSGustavo F. Padovan 
1063df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1073df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
1083df91ea2SAndrei Emeltchenko 			return c;
1090a708f8fSGustavo F. Padovan 	}
1103df91ea2SAndrei Emeltchenko 	return NULL;
111baa7e1faSGustavo F. Padovan }
1120a708f8fSGustavo F. Padovan 
1130a708f8fSGustavo F. Padovan /* Find channel with given SCID.
114ef191adeSMat Martineau  * Returns locked channel. */
1152d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1162d792818SGustavo Padovan 						 u16 cid)
1170a708f8fSGustavo F. Padovan {
11848454079SGustavo F. Padovan 	struct l2cap_chan *c;
119baa7e1faSGustavo F. Padovan 
1203df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
121baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
122ef191adeSMat Martineau 	if (c)
123ef191adeSMat Martineau 		l2cap_chan_lock(c);
1243df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1253df91ea2SAndrei Emeltchenko 
12648454079SGustavo F. Padovan 	return c;
1270a708f8fSGustavo F. Padovan }
1280a708f8fSGustavo F. Padovan 
129b1a130b7SMat Martineau /* Find channel with given DCID.
130b1a130b7SMat Martineau  * Returns locked channel.
131b1a130b7SMat Martineau  */
132b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
133b1a130b7SMat Martineau 						 u16 cid)
134b1a130b7SMat Martineau {
135b1a130b7SMat Martineau 	struct l2cap_chan *c;
136b1a130b7SMat Martineau 
137b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
138b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
139b1a130b7SMat Martineau 	if (c)
140b1a130b7SMat Martineau 		l2cap_chan_lock(c);
141b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
142b1a130b7SMat Martineau 
143b1a130b7SMat Martineau 	return c;
144b1a130b7SMat Martineau }
145b1a130b7SMat Martineau 
1462d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1472d792818SGustavo Padovan 						    u8 ident)
1480a708f8fSGustavo F. Padovan {
1493df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
150baa7e1faSGustavo F. Padovan 
1513df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1523df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1533df91ea2SAndrei Emeltchenko 			return c;
1540a708f8fSGustavo F. Padovan 	}
1553df91ea2SAndrei Emeltchenko 	return NULL;
156baa7e1faSGustavo F. Padovan }
1570a708f8fSGustavo F. Padovan 
1585b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1595b155ef9SMat Martineau 						  u8 ident)
1605b155ef9SMat Martineau {
1615b155ef9SMat Martineau 	struct l2cap_chan *c;
1625b155ef9SMat Martineau 
1635b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1645b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1655b155ef9SMat Martineau 	if (c)
1665b155ef9SMat Martineau 		l2cap_chan_lock(c);
1675b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1685b155ef9SMat Martineau 
1695b155ef9SMat Martineau 	return c;
1705b155ef9SMat Martineau }
1715b155ef9SMat Martineau 
17200f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
17300f62726SLuiz Augusto von Dentz 						      u8 src_type)
1749e4425ffSGustavo F. Padovan {
17523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1769e4425ffSGustavo F. Padovan 
17723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
17800f62726SLuiz Augusto von Dentz 		if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17900f62726SLuiz Augusto von Dentz 			continue;
18000f62726SLuiz Augusto von Dentz 
18100f62726SLuiz Augusto von Dentz 		if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
18200f62726SLuiz Augusto von Dentz 			continue;
18300f62726SLuiz Augusto von Dentz 
1847eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
18523691d75SGustavo F. Padovan 			return c;
1869e4425ffSGustavo F. Padovan 	}
187250938cbSSzymon Janc 	return NULL;
188250938cbSSzymon Janc }
1899e4425ffSGustavo F. Padovan 
1909e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1919e4425ffSGustavo F. Padovan {
19273b2ec18SGustavo F. Padovan 	int err;
19373b2ec18SGustavo F. Padovan 
194333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1959e4425ffSGustavo F. Padovan 
19600f62726SLuiz Augusto von Dentz 	if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
19773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
19873b2ec18SGustavo F. Padovan 		goto done;
1999e4425ffSGustavo F. Padovan 	}
2009e4425ffSGustavo F. Padovan 
20173b2ec18SGustavo F. Padovan 	if (psm) {
2029e4425ffSGustavo F. Padovan 		chan->psm = psm;
2039e4425ffSGustavo F. Padovan 		chan->sport = psm;
20473b2ec18SGustavo F. Padovan 		err = 0;
20573b2ec18SGustavo F. Padovan 	} else {
20692594a51SJohan Hedberg 		u16 p, start, end, incr;
20792594a51SJohan Hedberg 
20892594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
20992594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
21092594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
21192594a51SJohan Hedberg 			incr = 2;
21292594a51SJohan Hedberg 		} else {
21392594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
21492594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
21592594a51SJohan Hedberg 			incr = 1;
21692594a51SJohan Hedberg 		}
2179e4425ffSGustavo F. Padovan 
21873b2ec18SGustavo F. Padovan 		err = -EINVAL;
21992594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
22000f62726SLuiz Augusto von Dentz 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
22100f62726SLuiz Augusto von Dentz 							 chan->src_type)) {
22273b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
22373b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
22473b2ec18SGustavo F. Padovan 				err = 0;
22573b2ec18SGustavo F. Padovan 				break;
22673b2ec18SGustavo F. Padovan 			}
22773b2ec18SGustavo F. Padovan 	}
22873b2ec18SGustavo F. Padovan 
22973b2ec18SGustavo F. Padovan done:
230333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
23173b2ec18SGustavo F. Padovan 	return err;
2329e4425ffSGustavo F. Padovan }
2336b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2349e4425ffSGustavo F. Padovan 
2359e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2369e4425ffSGustavo F. Padovan {
237333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2389e4425ffSGustavo F. Padovan 
23914824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
24014824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
24114824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
24214824308SJohan Hedberg 
2439e4425ffSGustavo F. Padovan 	chan->scid = scid;
2449e4425ffSGustavo F. Padovan 
245333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2469e4425ffSGustavo F. Padovan 
2479e4425ffSGustavo F. Padovan 	return 0;
2489e4425ffSGustavo F. Padovan }
2499e4425ffSGustavo F. Padovan 
250baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2510a708f8fSGustavo F. Padovan {
252e77af755SJohan Hedberg 	u16 cid, dyn_end;
2530a708f8fSGustavo F. Padovan 
254e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
255e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
256e77af755SJohan Hedberg 	else
257e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
258e77af755SJohan Hedberg 
259ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
260baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2610a708f8fSGustavo F. Padovan 			return cid;
2620a708f8fSGustavo F. Padovan 	}
2630a708f8fSGustavo F. Padovan 
2640a708f8fSGustavo F. Padovan 	return 0;
2650a708f8fSGustavo F. Padovan }
2660a708f8fSGustavo F. Padovan 
267f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26889bc500eSGustavo F. Padovan {
26942d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
270badaaa00SGustavo F. Padovan 	       state_to_string(state));
271badaaa00SGustavo F. Padovan 
27289bc500eSGustavo F. Padovan 	chan->state = state;
27353f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
27489bc500eSGustavo F. Padovan }
27589bc500eSGustavo F. Padovan 
276f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
277f8e73017SGustavo Padovan 						int state, int err)
2782e0052e4SAndrei Emeltchenko {
279f8e73017SGustavo Padovan 	chan->state = state;
28053f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2812e0052e4SAndrei Emeltchenko }
2822e0052e4SAndrei Emeltchenko 
2832e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2842e0052e4SAndrei Emeltchenko {
285f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2862e0052e4SAndrei Emeltchenko }
2872e0052e4SAndrei Emeltchenko 
2884239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2894239d16fSMat Martineau {
2904239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2914239d16fSMat Martineau 	    chan->retrans_timeout) {
2924239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2934239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2944239d16fSMat Martineau 	}
2954239d16fSMat Martineau }
2964239d16fSMat Martineau 
2974239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2984239d16fSMat Martineau {
2994239d16fSMat Martineau 	__clear_retrans_timer(chan);
3004239d16fSMat Martineau 	if (chan->monitor_timeout) {
3014239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
3024239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
3034239d16fSMat Martineau 	}
3044239d16fSMat Martineau }
3054239d16fSMat Martineau 
306608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
307608bcc6dSMat Martineau 					       u16 seq)
308608bcc6dSMat Martineau {
309608bcc6dSMat Martineau 	struct sk_buff *skb;
310608bcc6dSMat Martineau 
311608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
312a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
313608bcc6dSMat Martineau 			return skb;
314608bcc6dSMat Martineau 	}
315608bcc6dSMat Martineau 
316608bcc6dSMat Martineau 	return NULL;
317608bcc6dSMat Martineau }
318608bcc6dSMat Martineau 
3193c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3203c588192SMat Martineau 
3213c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3223c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3233c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3243c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3253c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3263c588192SMat Martineau  * and removed from the head in constant time, without further memory
3273c588192SMat Martineau  * allocs or frees.
3283c588192SMat Martineau  */
3293c588192SMat Martineau 
3303c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3313c588192SMat Martineau {
3323c588192SMat Martineau 	size_t alloc_size, i;
3333c588192SMat Martineau 
3343c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3353c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3363c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3373c588192SMat Martineau 	 */
3383c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3393c588192SMat Martineau 
3406da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3413c588192SMat Martineau 	if (!seq_list->list)
3423c588192SMat Martineau 		return -ENOMEM;
3433c588192SMat Martineau 
3443c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3453c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3463c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3473c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3483c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3493c588192SMat Martineau 
3503c588192SMat Martineau 	return 0;
3513c588192SMat Martineau }
3523c588192SMat Martineau 
3533c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3543c588192SMat Martineau {
3553c588192SMat Martineau 	kfree(seq_list->list);
3563c588192SMat Martineau }
3573c588192SMat Martineau 
3583c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3593c588192SMat Martineau 					   u16 seq)
3603c588192SMat Martineau {
3613c588192SMat Martineau 	/* Constant-time check for list membership */
3623c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3633c588192SMat Martineau }
3643c588192SMat Martineau 
36503a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3663c588192SMat Martineau {
36703a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3683c588192SMat Martineau 	u16 mask = seq_list->mask;
3693c588192SMat Martineau 
3703c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3713c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3723c588192SMat Martineau 
3733c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3743c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3753c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3763c588192SMat Martineau 	}
3773c588192SMat Martineau 
3783c588192SMat Martineau 	return seq;
3793c588192SMat Martineau }
3803c588192SMat Martineau 
3813c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3823c588192SMat Martineau {
3833c588192SMat Martineau 	u16 i;
384f522ae36SGustavo Padovan 
385f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
386f522ae36SGustavo Padovan 		return;
387f522ae36SGustavo Padovan 
3883c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3893c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3903c588192SMat Martineau 
3913c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3923c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3933c588192SMat Martineau }
3943c588192SMat Martineau 
3953c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3963c588192SMat Martineau {
3973c588192SMat Martineau 	u16 mask = seq_list->mask;
3983c588192SMat Martineau 
3993c588192SMat Martineau 	/* All appends happen in constant time */
4003c588192SMat Martineau 
401f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
402f522ae36SGustavo Padovan 		return;
403f522ae36SGustavo Padovan 
4043c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4053c588192SMat Martineau 		seq_list->head = seq;
4063c588192SMat Martineau 	else
4073c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
4083c588192SMat Martineau 
4093c588192SMat Martineau 	seq_list->tail = seq;
4103c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4113c588192SMat Martineau }
4123c588192SMat Martineau 
413721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
414ab07801dSGustavo F. Padovan {
415721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
416721c4181SGustavo F. Padovan 					       chan_timer.work);
4173df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
418ab07801dSGustavo F. Padovan 	int reason;
419ab07801dSGustavo F. Padovan 
420e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
421ab07801dSGustavo F. Padovan 
4223df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4236c08fc89SManish Mandlik 	/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4246c08fc89SManish Mandlik 	 * this work. No need to call l2cap_chan_hold(chan) here again.
4256c08fc89SManish Mandlik 	 */
4266be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
427ab07801dSGustavo F. Padovan 
42889bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
429ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
43089bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
431ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
432ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
433ab07801dSGustavo F. Padovan 	else
434ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
435ab07801dSGustavo F. Padovan 
4360f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
437ab07801dSGustavo F. Padovan 
43880b98027SGustavo Padovan 	chan->ops->close(chan);
4393df91ea2SAndrei Emeltchenko 
4406c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
441371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4426c08fc89SManish Mandlik 
4436c08fc89SManish Mandlik 	mutex_unlock(&conn->chan_lock);
444ab07801dSGustavo F. Padovan }
445ab07801dSGustavo F. Padovan 
446eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4470a708f8fSGustavo F. Padovan {
44848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4490a708f8fSGustavo F. Padovan 
45048454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
45148454079SGustavo F. Padovan 	if (!chan)
45248454079SGustavo F. Padovan 		return NULL;
4530a708f8fSGustavo F. Padovan 
454c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
455c03b355eSAndrei Emeltchenko 
456ff714119SJohan Hedberg 	/* Set default lock nesting level */
457ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
458ff714119SJohan Hedberg 
459333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46023691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
461333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
46223691d75SGustavo F. Padovan 
463721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
464ab07801dSGustavo F. Padovan 
46589bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
46689bc500eSGustavo F. Padovan 
467144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
46871ba0e56SGustavo F. Padovan 
4692827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4702827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4712827011fSMat Martineau 
472eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
473abc545b8SSzymon Janc 
47448454079SGustavo F. Padovan 	return chan;
4750a708f8fSGustavo F. Padovan }
4766b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4770a708f8fSGustavo F. Padovan 
478144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4796ff5abbfSGustavo F. Padovan {
480144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
481144ad330SSyam Sidhardhan 
4824af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4834af66c69SJaganath Kanakkassery 
484333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
48523691d75SGustavo F. Padovan 	list_del(&chan->global_l);
486333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
48723691d75SGustavo F. Padovan 
4884af66c69SJaganath Kanakkassery 	kfree(chan);
4896ff5abbfSGustavo F. Padovan }
4906ff5abbfSGustavo F. Padovan 
49130648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
49230648372SJaganath Kanakkassery {
4932c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
49430648372SJaganath Kanakkassery 
495144ad330SSyam Sidhardhan 	kref_get(&c->kref);
49630648372SJaganath Kanakkassery }
49730648372SJaganath Kanakkassery 
49830648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
49930648372SJaganath Kanakkassery {
5002c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
50130648372SJaganath Kanakkassery 
502144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
50330648372SJaganath Kanakkassery }
5046b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
50530648372SJaganath Kanakkassery 
506bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
507bd4b1653SAndrei Emeltchenko {
508bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
509bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
510bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
511bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5126a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5136a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
514c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
515bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5166a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5176a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5186a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
519*3a9d54b1SArchie Pusaka 
5206a5e8165SJukka Rissanen 	chan->conf_state = 0;
521*3a9d54b1SArchie Pusaka 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
522bd4b1653SAndrei Emeltchenko 
523bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
524bd4b1653SAndrei Emeltchenko }
5256b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
526bd4b1653SAndrei Emeltchenko 
527ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
52838319713SJohan Hedberg {
5290ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5300ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5310ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
532ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
533fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
534fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
53596cd8eaaSLuiz Augusto von Dentz 	/* Give enough credits for a full packet */
53696cd8eaaSLuiz Augusto von Dentz 	chan->rx_credits = (chan->imtu / chan->mps) + 1;
5370ce43ce6SJohan Hedberg 
5380ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
53938319713SJohan Hedberg }
54038319713SJohan Hedberg 
54115f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
54215f02b91SLuiz Augusto von Dentz {
54315f02b91SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, tx_credits);
54415f02b91SLuiz Augusto von Dentz 
54515f02b91SLuiz Augusto von Dentz 	/* L2CAP implementations shall support a minimum MPS of 64 octets */
54615f02b91SLuiz Augusto von Dentz 	if (chan->mps < L2CAP_ECRED_MIN_MPS) {
54715f02b91SLuiz Augusto von Dentz 		chan->mps = L2CAP_ECRED_MIN_MPS;
54815f02b91SLuiz Augusto von Dentz 		chan->rx_credits = (chan->imtu / chan->mps) + 1;
54915f02b91SLuiz Augusto von Dentz 	}
55015f02b91SLuiz Augusto von Dentz }
55115f02b91SLuiz Augusto von Dentz 
55293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5530a708f8fSGustavo F. Padovan {
5540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
555097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5560a708f8fSGustavo F. Padovan 
5579f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5580a708f8fSGustavo F. Padovan 
5598c1d787bSGustavo F. Padovan 	chan->conn = conn;
5600a708f8fSGustavo F. Padovan 
5615491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5625491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
5630a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
564fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
56521626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
5660c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
5675491120eSAndrei Emeltchenko 		break;
5685491120eSAndrei Emeltchenko 
5695491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5700a708f8fSGustavo F. Padovan 		/* Connectionless socket */
571fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
572fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5730c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5745491120eSAndrei Emeltchenko 		break;
5755491120eSAndrei Emeltchenko 
5762338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
5772338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
578416fa752SAndrei Emeltchenko 		break;
579416fa752SAndrei Emeltchenko 
5805491120eSAndrei Emeltchenko 	default:
5810a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
582fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
583fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5840c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5850a708f8fSGustavo F. Padovan 	}
5860a708f8fSGustavo F. Padovan 
5878f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5888f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5898f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5908f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5918f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5928936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5938f7975b1SAndrei Emeltchenko 
594371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
595baa7e1faSGustavo F. Padovan 
596c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
597c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
598c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
5995ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
6005ee9891dSJohan Hedberg 
6013df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
602643162a8SAndrei Emeltchenko }
603643162a8SAndrei Emeltchenko 
604466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
605643162a8SAndrei Emeltchenko {
606643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
607643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
6083df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
6090a708f8fSGustavo F. Padovan }
6100a708f8fSGustavo F. Padovan 
611466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6120a708f8fSGustavo F. Padovan {
6138c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6140a708f8fSGustavo F. Padovan 
615c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
6160a708f8fSGustavo F. Padovan 
61749d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
61849d11741SJohan Hedberg 	       state_to_string(chan->state));
6190a708f8fSGustavo F. Padovan 
62072847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
62172847ce0SJohan Hedberg 
6220a708f8fSGustavo F. Padovan 	if (conn) {
62356f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
624baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6253df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6263d57dc68SGustavo F. Padovan 
627371fd835SUlisses Furquim 		l2cap_chan_put(chan);
628baa7e1faSGustavo F. Padovan 
6298c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6303cabbfdaSAndrei Emeltchenko 
631c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
632c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
633c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
634c16900cfSJohan Hedberg 		 */
635c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
636c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
63776a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
63856f60984SAndrei Emeltchenko 
63956f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
64056f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6410a708f8fSGustavo F. Padovan 	}
6420a708f8fSGustavo F. Padovan 
643419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
644419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
645419e08c1SAndrei Emeltchenko 
646419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
647419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
648419e08c1SAndrei Emeltchenko 	}
649419e08c1SAndrei Emeltchenko 
6502827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6516ff5abbfSGustavo F. Padovan 		return;
6522ead70b8SGustavo F. Padovan 
653ee556f66SGustavo Padovan 	switch(chan->mode) {
654ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
655ee556f66SGustavo Padovan 		break;
6560a708f8fSGustavo F. Padovan 
65738319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
65815f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
659177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
66038319713SJohan Hedberg 		break;
66138319713SJohan Hedberg 
662ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6631a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6641a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6651a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6660a708f8fSGustavo F. Padovan 
667f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6680a708f8fSGustavo F. Padovan 
6693c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6703c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
67119186c7bSGustavo A. R. Silva 		fallthrough;
672ee556f66SGustavo Padovan 
673ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
674ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
675ee556f66SGustavo Padovan 		break;
6760a708f8fSGustavo F. Padovan 	}
677ee556f66SGustavo Padovan 
678ee556f66SGustavo Padovan 	return;
6790a708f8fSGustavo F. Padovan }
6806b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
6810a708f8fSGustavo F. Padovan 
682da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
683da49b602SLuiz Augusto von Dentz 			      void *data)
684da49b602SLuiz Augusto von Dentz {
685da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
686da49b602SLuiz Augusto von Dentz 
687da49b602SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
688da49b602SLuiz Augusto von Dentz 		func(chan, data);
689da49b602SLuiz Augusto von Dentz 	}
690da49b602SLuiz Augusto von Dentz }
691da49b602SLuiz Augusto von Dentz 
692da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
693da49b602SLuiz Augusto von Dentz 		     void *data)
694da49b602SLuiz Augusto von Dentz {
695da49b602SLuiz Augusto von Dentz 	if (!conn)
696da49b602SLuiz Augusto von Dentz 		return;
697da49b602SLuiz Augusto von Dentz 
698da49b602SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
699da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, func, data);
700da49b602SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
701da49b602SLuiz Augusto von Dentz }
702da49b602SLuiz Augusto von Dentz 
703da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
704da49b602SLuiz Augusto von Dentz 
705f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
706387a33e3SJohan Hedberg {
707f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
708f3d82d0cSJohan Hedberg 					       id_addr_update_work);
709f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
710387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
711387a33e3SJohan Hedberg 
712387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
713387a33e3SJohan Hedberg 
714387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
715387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
716387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
717a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
718387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
719387a33e3SJohan Hedberg 	}
720387a33e3SJohan Hedberg 
721387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
722387a33e3SJohan Hedberg }
723387a33e3SJohan Hedberg 
72427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
72527e2d4c8SJohan Hedberg {
72627e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
72727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
72827e2d4c8SJohan Hedberg 	u16 result;
72927e2d4c8SJohan Hedberg 
73027e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
731571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
73227e2d4c8SJohan Hedberg 	else
733571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
73427e2d4c8SJohan Hedberg 
73527e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
73627e2d4c8SJohan Hedberg 
73727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
73827e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
7393916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
7400cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
74127e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
74227e2d4c8SJohan Hedberg 
74327e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
74427e2d4c8SJohan Hedberg 		       &rsp);
74527e2d4c8SJohan Hedberg }
74627e2d4c8SJohan Hedberg 
74715f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
74815f02b91SLuiz Augusto von Dentz {
74915f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
75015f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp rsp;
75115f02b91SLuiz Augusto von Dentz 	u16 result;
75215f02b91SLuiz Augusto von Dentz 
75315f02b91SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
75415f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHORIZATION;
75515f02b91SLuiz Augusto von Dentz 	else
75615f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
75715f02b91SLuiz Augusto von Dentz 
75815f02b91SLuiz Augusto von Dentz 	l2cap_state_change(chan, BT_DISCONN);
75915f02b91SLuiz Augusto von Dentz 
76015f02b91SLuiz Augusto von Dentz 	memset(&rsp, 0, sizeof(rsp));
76115f02b91SLuiz Augusto von Dentz 
76215f02b91SLuiz Augusto von Dentz 	rsp.result  = cpu_to_le16(result);
76315f02b91SLuiz Augusto von Dentz 
76415f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
76515f02b91SLuiz Augusto von Dentz 		       &rsp);
76615f02b91SLuiz Augusto von Dentz }
76715f02b91SLuiz Augusto von Dentz 
768791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
769791d60f7SJohan Hedberg {
770791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
771791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
772791d60f7SJohan Hedberg 	u16 result;
773791d60f7SJohan Hedberg 
774791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
775791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
776791d60f7SJohan Hedberg 	else
777791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
778791d60f7SJohan Hedberg 
779791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
780791d60f7SJohan Hedberg 
781791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
782791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
783791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
784dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
785791d60f7SJohan Hedberg 
786791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
787791d60f7SJohan Hedberg }
788791d60f7SJohan Hedberg 
7890f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
7904519de9aSGustavo F. Padovan {
7914519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7924519de9aSGustavo F. Padovan 
7937eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
7944519de9aSGustavo F. Padovan 
79589bc500eSGustavo F. Padovan 	switch (chan->state) {
7964519de9aSGustavo F. Padovan 	case BT_LISTEN:
797c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7984519de9aSGustavo F. Padovan 		break;
7994519de9aSGustavo F. Padovan 
8004519de9aSGustavo F. Padovan 	case BT_CONNECTED:
8014519de9aSGustavo F. Padovan 	case BT_CONFIG:
8027b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8038d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8045e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
8054519de9aSGustavo F. Padovan 		} else
8064519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
8074519de9aSGustavo F. Padovan 		break;
8084519de9aSGustavo F. Padovan 
8094519de9aSGustavo F. Padovan 	case BT_CONNECT2:
810791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
811791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
812791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
81315f02b91SLuiz Augusto von Dentz 			else if (conn->hcon->type == LE_LINK) {
81415f02b91SLuiz Augusto von Dentz 				switch (chan->mode) {
81515f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_LE_FLOWCTL:
81627e2d4c8SJohan Hedberg 					l2cap_chan_le_connect_reject(chan);
81715f02b91SLuiz Augusto von Dentz 					break;
81815f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_EXT_FLOWCTL:
81915f02b91SLuiz Augusto von Dentz 					l2cap_chan_ecred_connect_reject(chan);
82015f02b91SLuiz Augusto von Dentz 					break;
82115f02b91SLuiz Augusto von Dentz 				}
82215f02b91SLuiz Augusto von Dentz 			}
8234519de9aSGustavo F. Padovan 		}
8244519de9aSGustavo F. Padovan 
8254519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8264519de9aSGustavo F. Padovan 		break;
8274519de9aSGustavo F. Padovan 
8284519de9aSGustavo F. Padovan 	case BT_CONNECT:
8294519de9aSGustavo F. Padovan 	case BT_DISCONN:
8304519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8314519de9aSGustavo F. Padovan 		break;
8324519de9aSGustavo F. Padovan 
8334519de9aSGustavo F. Padovan 	default:
834c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8354519de9aSGustavo F. Padovan 		break;
8364519de9aSGustavo F. Padovan 	}
8374519de9aSGustavo F. Padovan }
8386b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8394519de9aSGustavo F. Padovan 
8404343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8410a708f8fSGustavo F. Padovan {
8426a974b50SMarcel Holtmann 	switch (chan->chan_type) {
8436a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
8444343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8450a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8467d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8470a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
8480a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8490a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
8500a708f8fSGustavo F. Padovan 		default:
8510a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8520a708f8fSGustavo F. Padovan 		}
8536a974b50SMarcel Holtmann 		break;
8543124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
855dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8563124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
8573124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
8583124b843SMarcel Holtmann 		}
8597d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
8607d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
8613124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
8623124b843SMarcel Holtmann 		else
8633124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
8643124b843SMarcel Holtmann 		break;
8656a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
866dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8674343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
8684343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
8690a708f8fSGustavo F. Padovan 
8707d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
8717d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
8720a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
8730a708f8fSGustavo F. Padovan 			else
8740a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
8756a974b50SMarcel Holtmann 		}
87619186c7bSGustavo A. R. Silva 		fallthrough;
87719186c7bSGustavo A. R. Silva 
8786a974b50SMarcel Holtmann 	default:
8794343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8800a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8817d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8820a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
8830a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8840a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
8850a708f8fSGustavo F. Padovan 		default:
8860a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8870a708f8fSGustavo F. Padovan 		}
8886a974b50SMarcel Holtmann 		break;
8890a708f8fSGustavo F. Padovan 	}
8900a708f8fSGustavo F. Padovan }
8910a708f8fSGustavo F. Padovan 
8920a708f8fSGustavo F. Padovan /* Service level security */
893e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
8940a708f8fSGustavo F. Padovan {
8958c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8960a708f8fSGustavo F. Padovan 	__u8 auth_type;
8970a708f8fSGustavo F. Padovan 
898a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
899a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
900a17de2feSJohan Hedberg 
9014343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
9020a708f8fSGustavo F. Padovan 
903e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
904e7cafc45SJohan Hedberg 				 initiator);
9050a708f8fSGustavo F. Padovan }
9060a708f8fSGustavo F. Padovan 
907b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9080a708f8fSGustavo F. Padovan {
9090a708f8fSGustavo F. Padovan 	u8 id;
9100a708f8fSGustavo F. Padovan 
9110a708f8fSGustavo F. Padovan 	/* Get next available identificator.
9120a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
9130a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
9140a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
9150a708f8fSGustavo F. Padovan 	 */
9160a708f8fSGustavo F. Padovan 
9175a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
9180a708f8fSGustavo F. Padovan 
9190a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
9200a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
9210a708f8fSGustavo F. Padovan 
9220a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
9230a708f8fSGustavo F. Padovan 
9245a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
9250a708f8fSGustavo F. Padovan 
9260a708f8fSGustavo F. Padovan 	return id;
9270a708f8fSGustavo F. Padovan }
9280a708f8fSGustavo F. Padovan 
9292d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9302d792818SGustavo Padovan 			   void *data)
9310a708f8fSGustavo F. Padovan {
9320a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9330a708f8fSGustavo F. Padovan 	u8 flags;
9340a708f8fSGustavo F. Padovan 
9350a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
9360a708f8fSGustavo F. Padovan 
9370a708f8fSGustavo F. Padovan 	if (!skb)
9380a708f8fSGustavo F. Padovan 		return;
9390a708f8fSGustavo F. Padovan 
940f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
941f6af675eSSteven Walter 	 * not support auto-flushing packets) */
942f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
943f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
9440a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
9450a708f8fSGustavo F. Padovan 	else
9460a708f8fSGustavo F. Padovan 		flags = ACL_START;
9470a708f8fSGustavo F. Padovan 
94814b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9495e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
95014b12d0bSJaikumar Ganesh 
95173d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
9520a708f8fSGustavo F. Padovan }
9530a708f8fSGustavo F. Padovan 
95402b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
95502b0fbb9SMat Martineau {
95602b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
95702b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
95802b0fbb9SMat Martineau }
95902b0fbb9SMat Martineau 
96073d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
96173d80debSLuiz Augusto von Dentz {
96273d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
96373d80debSLuiz Augusto von Dentz 	u16 flags;
96473d80debSLuiz Augusto von Dentz 
96573d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
96673d80debSLuiz Augusto von Dentz 	       skb->priority);
96773d80debSLuiz Augusto von Dentz 
968d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
969d5f8a75dSMat Martineau 		if (chan->hs_hchan)
970d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
971d5f8a75dSMat Martineau 		else
972d5f8a75dSMat Martineau 			kfree_skb(skb);
973d5f8a75dSMat Martineau 
974d5f8a75dSMat Martineau 		return;
975d5f8a75dSMat Martineau 	}
976d5f8a75dSMat Martineau 
977f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
978f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
979f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
980f6af675eSSteven Walter 	 */
981f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
982f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
983f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
98473d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
98573d80debSLuiz Augusto von Dentz 	else
98673d80debSLuiz Augusto von Dentz 		flags = ACL_START;
98773d80debSLuiz Augusto von Dentz 
98873d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
98973d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
9900a708f8fSGustavo F. Padovan }
9910a708f8fSGustavo F. Padovan 
992b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
993b5c6aaedSMat Martineau {
994b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
995b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
996b5c6aaedSMat Martineau 
997b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
998b5c6aaedSMat Martineau 		/* S-Frame */
999b5c6aaedSMat Martineau 		control->sframe = 1;
1000b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1001b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
1002b5c6aaedSMat Martineau 
1003b5c6aaedSMat Martineau 		control->sar = 0;
1004b5c6aaedSMat Martineau 		control->txseq = 0;
1005b5c6aaedSMat Martineau 	} else {
1006b5c6aaedSMat Martineau 		/* I-Frame */
1007b5c6aaedSMat Martineau 		control->sframe = 0;
1008b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1009b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
1010b5c6aaedSMat Martineau 
1011b5c6aaedSMat Martineau 		control->poll = 0;
1012b5c6aaedSMat Martineau 		control->super = 0;
1013b5c6aaedSMat Martineau 	}
1014b5c6aaedSMat Martineau }
1015b5c6aaedSMat Martineau 
1016b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1017b5c6aaedSMat Martineau {
1018b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1019b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1020b5c6aaedSMat Martineau 
1021b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1022b5c6aaedSMat Martineau 		/* S-Frame */
1023b5c6aaedSMat Martineau 		control->sframe = 1;
1024b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1025b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1026b5c6aaedSMat Martineau 
1027b5c6aaedSMat Martineau 		control->sar = 0;
1028b5c6aaedSMat Martineau 		control->txseq = 0;
1029b5c6aaedSMat Martineau 	} else {
1030b5c6aaedSMat Martineau 		/* I-Frame */
1031b5c6aaedSMat Martineau 		control->sframe = 0;
1032b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1033b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1034b5c6aaedSMat Martineau 
1035b5c6aaedSMat Martineau 		control->poll = 0;
1036b5c6aaedSMat Martineau 		control->super = 0;
1037b5c6aaedSMat Martineau 	}
1038b5c6aaedSMat Martineau }
1039b5c6aaedSMat Martineau 
1040b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1041b5c6aaedSMat Martineau 				    struct sk_buff *skb)
1042b5c6aaedSMat Martineau {
1043b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1044b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
1045a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1046cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1047b5c6aaedSMat Martineau 	} else {
1048b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
1049a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1050cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1051b5c6aaedSMat Martineau 	}
1052b5c6aaedSMat Martineau }
1053b5c6aaedSMat Martineau 
1054b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1055b5c6aaedSMat Martineau {
1056b5c6aaedSMat Martineau 	u32 packed;
1057b5c6aaedSMat Martineau 
1058b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1059b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1060b5c6aaedSMat Martineau 
1061b5c6aaedSMat Martineau 	if (control->sframe) {
1062b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1063b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1064b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1065b5c6aaedSMat Martineau 	} else {
1066b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
1067b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1068b5c6aaedSMat Martineau 	}
1069b5c6aaedSMat Martineau 
1070b5c6aaedSMat Martineau 	return packed;
1071b5c6aaedSMat Martineau }
1072b5c6aaedSMat Martineau 
1073b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1074b5c6aaedSMat Martineau {
1075b5c6aaedSMat Martineau 	u16 packed;
1076b5c6aaedSMat Martineau 
1077b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1078b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1079b5c6aaedSMat Martineau 
1080b5c6aaedSMat Martineau 	if (control->sframe) {
1081b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1082b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1083b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1084b5c6aaedSMat Martineau 	} else {
1085b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1086b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1087b5c6aaedSMat Martineau 	}
1088b5c6aaedSMat Martineau 
1089b5c6aaedSMat Martineau 	return packed;
1090b5c6aaedSMat Martineau }
1091b5c6aaedSMat Martineau 
1092b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1093b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1094b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1095b5c6aaedSMat Martineau {
1096b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1097b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1098b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1099b5c6aaedSMat Martineau 	} else {
1100b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1101b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1102b5c6aaedSMat Martineau 	}
1103b5c6aaedSMat Martineau }
1104b5c6aaedSMat Martineau 
1105ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1106ba7aa64fSGustavo Padovan {
1107ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1108ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1109ba7aa64fSGustavo Padovan 	else
1110ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1111ba7aa64fSGustavo Padovan }
1112ba7aa64fSGustavo Padovan 
1113a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1114a67d7f6fSMat Martineau 					       u32 control)
11150a708f8fSGustavo F. Padovan {
11160a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
11170a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1118ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
11190a708f8fSGustavo F. Padovan 
11200a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
112103a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
11220a708f8fSGustavo F. Padovan 
1123a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
11240a708f8fSGustavo F. Padovan 
11250a708f8fSGustavo F. Padovan 	if (!skb)
1126a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
11270a708f8fSGustavo F. Padovan 
11284df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
11290a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1130fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
113188843ab0SAndrei Emeltchenko 
1132a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1133a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1134a67d7f6fSMat Martineau 	else
1135a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11360a708f8fSGustavo F. Padovan 
113747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1138a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
113903a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
11400a708f8fSGustavo F. Padovan 	}
11410a708f8fSGustavo F. Padovan 
114273d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1143a67d7f6fSMat Martineau 	return skb;
1144a67d7f6fSMat Martineau }
1145a67d7f6fSMat Martineau 
1146a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1147a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1148a67d7f6fSMat Martineau {
1149a67d7f6fSMat Martineau 	struct sk_buff *skb;
1150a67d7f6fSMat Martineau 	u32 control_field;
1151a67d7f6fSMat Martineau 
1152a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1153a67d7f6fSMat Martineau 
1154a67d7f6fSMat Martineau 	if (!control->sframe)
1155a67d7f6fSMat Martineau 		return;
1156a67d7f6fSMat Martineau 
1157b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1158b99e13adSMat Martineau 		return;
1159b99e13adSMat Martineau 
1160a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1161a67d7f6fSMat Martineau 	    !control->poll)
1162a67d7f6fSMat Martineau 		control->final = 1;
1163a67d7f6fSMat Martineau 
1164a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1165a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1166a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1167a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1168a67d7f6fSMat Martineau 
1169a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1170a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1171a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1172a67d7f6fSMat Martineau 	}
1173a67d7f6fSMat Martineau 
1174a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1175a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1176a67d7f6fSMat Martineau 
1177a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1178a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1179a67d7f6fSMat Martineau 	else
1180a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1181a67d7f6fSMat Martineau 
1182a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1183a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
118473d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
11850a708f8fSGustavo F. Padovan }
11860a708f8fSGustavo F. Padovan 
1187c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11880a708f8fSGustavo F. Padovan {
1189c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
11900a708f8fSGustavo F. Padovan 
1191c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1192c9e3d5e0SMat Martineau 
1193c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1194c9e3d5e0SMat Martineau 	control.sframe = 1;
1195c9e3d5e0SMat Martineau 	control.poll = poll;
1196c9e3d5e0SMat Martineau 
1197c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1198c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1199c9e3d5e0SMat Martineau 	else
1200c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1201c9e3d5e0SMat Martineau 
1202c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1203c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
12040a708f8fSGustavo F. Padovan }
12050a708f8fSGustavo F. Padovan 
1206b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12070a708f8fSGustavo F. Padovan {
12085ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12095ff6f34dSJohan Hedberg 		return true;
12105ff6f34dSJohan Hedberg 
1211c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12120a708f8fSGustavo F. Padovan }
12130a708f8fSGustavo F. Padovan 
121493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
121593c3e8f5SAndrei Emeltchenko {
121693c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12171df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
12181df7b17aSMarcel Holtmann 	bool amp_available = false;
121993c3e8f5SAndrei Emeltchenko 
12200bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
12211df7b17aSMarcel Holtmann 		return false;
12221df7b17aSMarcel Holtmann 
12230bd49fc7SJohan Hedberg 	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
12241df7b17aSMarcel Holtmann 		return false;
12251df7b17aSMarcel Holtmann 
12261df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
12271df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
12281df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
12291df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
12301df7b17aSMarcel Holtmann 			amp_available = true;
12311df7b17aSMarcel Holtmann 			break;
12321df7b17aSMarcel Holtmann 		}
12331df7b17aSMarcel Holtmann 	}
12341df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
12351df7b17aSMarcel Holtmann 
12361df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
12371df7b17aSMarcel Holtmann 		return amp_available;
1238848566b3SMarcel Holtmann 
123993c3e8f5SAndrei Emeltchenko 	return false;
124093c3e8f5SAndrei Emeltchenko }
124193c3e8f5SAndrei Emeltchenko 
12425ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
12435ce66b59SAndrei Emeltchenko {
12445ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
12455ce66b59SAndrei Emeltchenko 	return true;
12465ce66b59SAndrei Emeltchenko }
12475ce66b59SAndrei Emeltchenko 
12482766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12499b27f350SAndrei Emeltchenko {
12509b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12519b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
12529b27f350SAndrei Emeltchenko 
12539b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
12549b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
12559b27f350SAndrei Emeltchenko 
12569b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
12579b27f350SAndrei Emeltchenko 
12589b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12599b27f350SAndrei Emeltchenko 
12609b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12619b27f350SAndrei Emeltchenko }
12629b27f350SAndrei Emeltchenko 
12638eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
12648eb200bdSMat Martineau {
12658eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
12668eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
12678eb200bdSMat Martineau 	req.psm  = chan->psm;
12688eb200bdSMat Martineau 	req.amp_id = amp_id;
12698eb200bdSMat Martineau 
12708eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
12718eb200bdSMat Martineau 
12728eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
12738eb200bdSMat Martineau 		       sizeof(req), &req);
12748eb200bdSMat Martineau }
12758eb200bdSMat Martineau 
127602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
127702b0fbb9SMat Martineau {
127802b0fbb9SMat Martineau 	struct sk_buff *skb;
127902b0fbb9SMat Martineau 
128002b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
128102b0fbb9SMat Martineau 
128202b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
128302b0fbb9SMat Martineau 		return;
128402b0fbb9SMat Martineau 
128502b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
128602b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
128702b0fbb9SMat Martineau 	__clear_ack_timer(chan);
128802b0fbb9SMat Martineau 
128902b0fbb9SMat Martineau 	chan->retry_count = 0;
129002b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
1291a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.retries)
1292a4368ff3SJohan Hedberg 			bt_cb(skb)->l2cap.retries = 1;
129302b0fbb9SMat Martineau 		else
129402b0fbb9SMat Martineau 			break;
129502b0fbb9SMat Martineau 	}
129602b0fbb9SMat Martineau 
129702b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
129802b0fbb9SMat Martineau 
129902b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
130002b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
130102b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
130202b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
130302b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
130402b0fbb9SMat Martineau 
130502b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
130602b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
130702b0fbb9SMat Martineau 
130802b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
130902b0fbb9SMat Martineau }
131002b0fbb9SMat Martineau 
13115f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
13125f3847a4SMat Martineau {
13135f3847a4SMat Martineau 	u8 move_role = chan->move_role;
13145f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
13155f3847a4SMat Martineau 
13165f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
13175f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
13185f3847a4SMat Martineau 
13195f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
13205f3847a4SMat Martineau 		return;
13215f3847a4SMat Martineau 
13225f3847a4SMat Martineau 	switch (move_role) {
13235f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
13245f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
13255f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
13265f3847a4SMat Martineau 		break;
13275f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
13285f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
13295f3847a4SMat Martineau 		break;
13305f3847a4SMat Martineau 	}
13315f3847a4SMat Martineau }
13325f3847a4SMat Martineau 
13339f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
13349f0caeb1SVinicius Costa Gomes {
1335315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1336315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1337315917e0SJohan Hedberg 	 * procedure is complete.
1338315917e0SJohan Hedberg 	 */
1339315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1340315917e0SJohan Hedberg 		return;
1341315917e0SJohan Hedberg 
13422827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
13439f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
13449f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
13459f0caeb1SVinicius Costa Gomes 
134615f02b91SLuiz Augusto von Dentz 	switch (chan->mode) {
134715f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_LE_FLOWCTL:
134815f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
134915f02b91SLuiz Augusto von Dentz 		if (!chan->tx_credits)
13500ce43ce6SJohan Hedberg 			chan->ops->suspend(chan);
135115f02b91SLuiz Augusto von Dentz 		break;
135215f02b91SLuiz Augusto von Dentz 	}
1353177f8f2bSJohan Hedberg 
135454a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
13559f0caeb1SVinicius Costa Gomes 
135654a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
13579f0caeb1SVinicius Costa Gomes }
13589f0caeb1SVinicius Costa Gomes 
1359f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1360f1496deeSJohan Hedberg {
1361f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1362f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1363f1496deeSJohan Hedberg 
1364595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1365595177f3SJohan Hedberg 		return;
1366595177f3SJohan Hedberg 
13674b6e228eSLuiz Augusto von Dentz 	if (!chan->imtu)
13684b6e228eSLuiz Augusto von Dentz 		chan->imtu = chan->conn->mtu;
13694b6e228eSLuiz Augusto von Dentz 
1370ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1371fe149310SLuiz Augusto von Dentz 
1372f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1373f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1374f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
13753916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
13760cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1377f1496deeSJohan Hedberg 
1378f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1379f1496deeSJohan Hedberg 
1380f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1381f1496deeSJohan Hedberg 		       sizeof(req), &req);
1382f1496deeSJohan Hedberg }
1383f1496deeSJohan Hedberg 
1384da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
138515f02b91SLuiz Augusto von Dentz 	struct {
138615f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_req req;
1387da49b602SLuiz Augusto von Dentz 		__le16 scid[5];
138815f02b91SLuiz Augusto von Dentz 	} __packed pdu;
1389da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
1390da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1391da49b602SLuiz Augusto von Dentz 	int count;
1392da49b602SLuiz Augusto von Dentz };
1393da49b602SLuiz Augusto von Dentz 
1394da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1395da49b602SLuiz Augusto von Dentz {
1396da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data *conn = data;
1397da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1398da49b602SLuiz Augusto von Dentz 
1399da49b602SLuiz Augusto von Dentz 	if (chan == conn->chan)
1400da49b602SLuiz Augusto von Dentz 		return;
1401da49b602SLuiz Augusto von Dentz 
1402da49b602SLuiz Augusto von Dentz 	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1403da49b602SLuiz Augusto von Dentz 		return;
1404da49b602SLuiz Augusto von Dentz 
1405da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
1406da49b602SLuiz Augusto von Dentz 
1407da49b602SLuiz Augusto von Dentz 	/* Only add deferred channels with the same PID/PSM */
1408da49b602SLuiz Augusto von Dentz 	if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1409da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1410da49b602SLuiz Augusto von Dentz 		return;
141115f02b91SLuiz Augusto von Dentz 
141215f02b91SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
141315f02b91SLuiz Augusto von Dentz 		return;
141415f02b91SLuiz Augusto von Dentz 
141515f02b91SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
141615f02b91SLuiz Augusto von Dentz 
1417da49b602SLuiz Augusto von Dentz 	/* Set the same ident so we can match on the rsp */
1418da49b602SLuiz Augusto von Dentz 	chan->ident = conn->chan->ident;
1419da49b602SLuiz Augusto von Dentz 
1420da49b602SLuiz Augusto von Dentz 	/* Include all channels deferred */
1421da49b602SLuiz Augusto von Dentz 	conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1422da49b602SLuiz Augusto von Dentz 
1423da49b602SLuiz Augusto von Dentz 	conn->count++;
1424da49b602SLuiz Augusto von Dentz }
1425da49b602SLuiz Augusto von Dentz 
1426da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1427da49b602SLuiz Augusto von Dentz {
1428da49b602SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
1429da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data data;
1430da49b602SLuiz Augusto von Dentz 
1431da49b602SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1432da49b602SLuiz Augusto von Dentz 		return;
1433da49b602SLuiz Augusto von Dentz 
1434da49b602SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1435da49b602SLuiz Augusto von Dentz 		return;
1436da49b602SLuiz Augusto von Dentz 
1437da49b602SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
1438da49b602SLuiz Augusto von Dentz 
1439da49b602SLuiz Augusto von Dentz 	data.pdu.req.psm     = chan->psm;
1440da49b602SLuiz Augusto von Dentz 	data.pdu.req.mtu     = cpu_to_le16(chan->imtu);
1441da49b602SLuiz Augusto von Dentz 	data.pdu.req.mps     = cpu_to_le16(chan->mps);
1442da49b602SLuiz Augusto von Dentz 	data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1443da49b602SLuiz Augusto von Dentz 	data.pdu.scid[0]     = cpu_to_le16(chan->scid);
144415f02b91SLuiz Augusto von Dentz 
144515f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
1446da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1447da49b602SLuiz Augusto von Dentz 
1448da49b602SLuiz Augusto von Dentz 	data.count = 1;
1449da49b602SLuiz Augusto von Dentz 	data.chan = chan;
1450da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1451da49b602SLuiz Augusto von Dentz 
1452da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
145315f02b91SLuiz Augusto von Dentz 
145415f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1455da49b602SLuiz Augusto von Dentz 		       sizeof(data.pdu.req) + data.count * sizeof(__le16),
1456da49b602SLuiz Augusto von Dentz 		       &data.pdu);
145715f02b91SLuiz Augusto von Dentz }
145815f02b91SLuiz Augusto von Dentz 
1459f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1460f1496deeSJohan Hedberg {
1461f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1462f1496deeSJohan Hedberg 
1463f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1464f1496deeSJohan Hedberg 		return;
1465f1496deeSJohan Hedberg 
1466f1496deeSJohan Hedberg 	if (!chan->psm) {
1467f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1468f1496deeSJohan Hedberg 		return;
1469f1496deeSJohan Hedberg 	}
1470f1496deeSJohan Hedberg 
147115f02b91SLuiz Augusto von Dentz 	if (chan->state == BT_CONNECT) {
147215f02b91SLuiz Augusto von Dentz 		if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
147315f02b91SLuiz Augusto von Dentz 			l2cap_ecred_connect(chan);
147415f02b91SLuiz Augusto von Dentz 		else
1475f1496deeSJohan Hedberg 			l2cap_le_connect(chan);
1476f1496deeSJohan Hedberg 	}
147715f02b91SLuiz Augusto von Dentz }
1478f1496deeSJohan Hedberg 
147993c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
148093c3e8f5SAndrei Emeltchenko {
148193c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
148293c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
148393c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1484f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1485f1496deeSJohan Hedberg 		l2cap_le_start(chan);
148693c3e8f5SAndrei Emeltchenko 	} else {
148793c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
148893c3e8f5SAndrei Emeltchenko 	}
148993c3e8f5SAndrei Emeltchenko }
149093c3e8f5SAndrei Emeltchenko 
1491aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
14920a708f8fSGustavo F. Padovan {
14930a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1494aeaeb4bbSJohan Hedberg 
1495aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1496aeaeb4bbSJohan Hedberg 		return;
1497aeaeb4bbSJohan Hedberg 
1498dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
14990a708f8fSGustavo F. Padovan 
15000a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
15010a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
15020a708f8fSGustavo F. Padovan 
1503ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
15040a708f8fSGustavo F. Padovan 
15052d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
15062d792818SGustavo Padovan 		       sizeof(req), &req);
15070a708f8fSGustavo F. Padovan }
1508aeaeb4bbSJohan Hedberg 
1509693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1510693cd8ceSMarcel Holtmann {
1511693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1512693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1513693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1514693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1515693cd8ceSMarcel Holtmann 	 *
1516693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1517693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1518693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1519693cd8ceSMarcel Holtmann 	 */
1520288c0697SArchie Pusaka 	int min_key_size = hcon->hdev->min_enc_key_size;
1521288c0697SArchie Pusaka 
1522288c0697SArchie Pusaka 	/* On FIPS security level, key size must be 16 bytes */
1523288c0697SArchie Pusaka 	if (hcon->sec_level == BT_SECURITY_FIPS)
1524288c0697SArchie Pusaka 		min_key_size = 16;
1525288c0697SArchie Pusaka 
1526693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1527288c0697SArchie Pusaka 		hcon->enc_key_size >= min_key_size);
1528693cd8ceSMarcel Holtmann }
1529693cd8ceSMarcel Holtmann 
1530aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1531aeaeb4bbSJohan Hedberg {
1532aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1533aeaeb4bbSJohan Hedberg 
1534aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1535aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1536aeaeb4bbSJohan Hedberg 		return;
1537aeaeb4bbSJohan Hedberg 	}
1538aeaeb4bbSJohan Hedberg 
1539aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1540aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1541aeaeb4bbSJohan Hedberg 		return;
1542aeaeb4bbSJohan Hedberg 	}
1543aeaeb4bbSJohan Hedberg 
1544aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1545aeaeb4bbSJohan Hedberg 		return;
1546aeaeb4bbSJohan Hedberg 
1547693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1548693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1549693cd8ceSMarcel Holtmann 		return;
1550693cd8ceSMarcel Holtmann 
1551693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1552aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1553693cd8ceSMarcel Holtmann 	else
1554693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
15550a708f8fSGustavo F. Padovan }
15560a708f8fSGustavo F. Padovan 
15570a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
15580a708f8fSGustavo F. Padovan {
15590a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
15600a708f8fSGustavo F. Padovan 	if (!disable_ertm)
15610a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
15620a708f8fSGustavo F. Padovan 
15630a708f8fSGustavo F. Padovan 	switch (mode) {
15640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
15650a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
15660a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
15670a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
15680a708f8fSGustavo F. Padovan 	default:
15690a708f8fSGustavo F. Padovan 		return 0x00;
15700a708f8fSGustavo F. Padovan 	}
15710a708f8fSGustavo F. Padovan }
15720a708f8fSGustavo F. Padovan 
15735e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
15740a708f8fSGustavo F. Padovan {
15755e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
15760a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
15770a708f8fSGustavo F. Padovan 
15780a708f8fSGustavo F. Padovan 	if (!conn)
15790a708f8fSGustavo F. Padovan 		return;
15800a708f8fSGustavo F. Padovan 
1581aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
15821a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
15831a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
15841a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
15850a708f8fSGustavo F. Padovan 	}
15860a708f8fSGustavo F. Padovan 
15872338a7e0SJohan Hedberg 	if (chan->scid == L2CAP_CID_A2MP) {
1588d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1589416fa752SAndrei Emeltchenko 		return;
1590416fa752SAndrei Emeltchenko 	}
1591416fa752SAndrei Emeltchenko 
1592fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1593fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
15942d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
15952d792818SGustavo Padovan 		       sizeof(req), &req);
15960a708f8fSGustavo F. Padovan 
1597f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
15980a708f8fSGustavo F. Padovan }
15990a708f8fSGustavo F. Padovan 
16000a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
16010a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
16020a708f8fSGustavo F. Padovan {
16033df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
16040a708f8fSGustavo F. Padovan 
16050a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
16060a708f8fSGustavo F. Padovan 
16073df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16080a708f8fSGustavo F. Padovan 
16093df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
16106be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16110a708f8fSGustavo F. Padovan 
1612715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1613aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
16146be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
16150a708f8fSGustavo F. Padovan 			continue;
16160a708f8fSGustavo F. Padovan 		}
16170a708f8fSGustavo F. Padovan 
161889bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1619e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1620b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
16216be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16220a708f8fSGustavo F. Padovan 				continue;
16230a708f8fSGustavo F. Padovan 			}
16240a708f8fSGustavo F. Padovan 
1625c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1626c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1627c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
16280f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
16296be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16300a708f8fSGustavo F. Padovan 				continue;
16310a708f8fSGustavo F. Padovan 			}
16320a708f8fSGustavo F. Padovan 
1633693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
163493c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1635693cd8ceSMarcel Holtmann 			else
1636693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
16370a708f8fSGustavo F. Padovan 
163889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
16390a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
16400a708f8fSGustavo F. Padovan 			char buf[128];
1641fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1642fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
16430a708f8fSGustavo F. Padovan 
1644e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1645bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1646dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1647dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
16482dc4e510SGustavo Padovan 					chan->ops->defer(chan);
16490a708f8fSGustavo F. Padovan 
16500a708f8fSGustavo F. Padovan 				} else {
1651acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1652dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1653dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
16540a708f8fSGustavo F. Padovan 				}
16550a708f8fSGustavo F. Padovan 			} else {
1656dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1657dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
16580a708f8fSGustavo F. Padovan 			}
16590a708f8fSGustavo F. Padovan 
1660fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1661fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
16620a708f8fSGustavo F. Padovan 
1663c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
16640a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
16656be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16660a708f8fSGustavo F. Padovan 				continue;
16670a708f8fSGustavo F. Padovan 			}
16680a708f8fSGustavo F. Padovan 
1669c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
16700a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1671e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
167273ffa904SGustavo F. Padovan 			chan->num_conf_req++;
16730a708f8fSGustavo F. Padovan 		}
16740a708f8fSGustavo F. Padovan 
16756be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16760a708f8fSGustavo F. Padovan 	}
16770a708f8fSGustavo F. Padovan 
16783df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16790a708f8fSGustavo F. Padovan }
16800a708f8fSGustavo F. Padovan 
1681b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1682b62f328bSVille Tervo {
1683cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1684dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1685b62f328bSVille Tervo 
1686e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1687b62f328bSVille Tervo 
1688e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1689e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1690e760ec12SJohan Hedberg 	 */
1691e760ec12SJohan Hedberg 	if (hcon->out)
1692e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1693cc8dba2bSMarcel Holtmann 
169480afeb6cSMarcel Holtmann 	/* For LE slave connections, make sure the connection interval
169580afeb6cSMarcel Holtmann 	 * is in the range of the minium and maximum interval that has
169680afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
169780afeb6cSMarcel Holtmann 	 * the connection update procedure.
169880afeb6cSMarcel Holtmann 	 */
169940bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
170080afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
170180afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
170280afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
170380afeb6cSMarcel Holtmann 
170480afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
170580afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
170680afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
170780afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
170880afeb6cSMarcel Holtmann 
170980afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
171080afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
171180afeb6cSMarcel Holtmann 	}
1712b62f328bSVille Tervo }
1713b62f328bSVille Tervo 
17140a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
17150a708f8fSGustavo F. Padovan {
171648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1717cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
17180a708f8fSGustavo F. Padovan 
17190a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17200a708f8fSGustavo F. Padovan 
1721aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1722aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1723aeaeb4bbSJohan Hedberg 
1724e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1725e760ec12SJohan Hedberg 
17263df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1727baa7e1faSGustavo F. Padovan 
17286be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17290a708f8fSGustavo F. Padovan 
17302338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
1731416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1732416fa752SAndrei Emeltchenko 			continue;
1733416fa752SAndrei Emeltchenko 		}
1734416fa752SAndrei Emeltchenko 
1735cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1736f1496deeSJohan Hedberg 			l2cap_le_start(chan);
173763128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1738aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
173974e75740SGustavo Padovan 				l2cap_chan_ready(chan);
17401c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1741fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
17421c244f79SGustavo Padovan 		}
17430a708f8fSGustavo F. Padovan 
17446be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17450a708f8fSGustavo F. Padovan 	}
17460a708f8fSGustavo F. Padovan 
17473df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
174861a939c6SJohan Hedberg 
174979a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
175079a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
175179a05727SJohan Hedberg 
175261a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
17530a708f8fSGustavo F. Padovan }
17540a708f8fSGustavo F. Padovan 
17550a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
17560a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
17570a708f8fSGustavo F. Padovan {
175848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
17590a708f8fSGustavo F. Padovan 
17600a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17610a708f8fSGustavo F. Padovan 
17623df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17630a708f8fSGustavo F. Padovan 
17643df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1765ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
17661d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
17670a708f8fSGustavo F. Padovan 	}
17680a708f8fSGustavo F. Padovan 
17693df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17700a708f8fSGustavo F. Padovan }
17710a708f8fSGustavo F. Padovan 
1772f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
17730a708f8fSGustavo F. Padovan {
1774f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1775030013d8SGustavo F. Padovan 					       info_timer.work);
17760a708f8fSGustavo F. Padovan 
17770a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
17780a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
17790a708f8fSGustavo F. Padovan 
17800a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
17810a708f8fSGustavo F. Padovan }
17820a708f8fSGustavo F. Padovan 
17832c8e1411SDavid Herrmann /*
17842c8e1411SDavid Herrmann  * l2cap_user
17852c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
17862c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
17872c8e1411SDavid Herrmann  * during unregistration.
17882c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
17892c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
17902c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
17912c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
17922c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
17932c8e1411SDavid Herrmann  * any time if they don't.
17942c8e1411SDavid Herrmann  */
17952c8e1411SDavid Herrmann 
17962c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
17972c8e1411SDavid Herrmann {
17982c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
17992c8e1411SDavid Herrmann 	int ret;
18002c8e1411SDavid Herrmann 
18012c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
18022c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
18032c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
18042c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
18052c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
18062c8e1411SDavid Herrmann 	 * here, too. */
18072c8e1411SDavid Herrmann 
18082c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18092c8e1411SDavid Herrmann 
1810835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
18112c8e1411SDavid Herrmann 		ret = -EINVAL;
18122c8e1411SDavid Herrmann 		goto out_unlock;
18132c8e1411SDavid Herrmann 	}
18142c8e1411SDavid Herrmann 
18152c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
18162c8e1411SDavid Herrmann 	if (!conn->hchan) {
18172c8e1411SDavid Herrmann 		ret = -ENODEV;
18182c8e1411SDavid Herrmann 		goto out_unlock;
18192c8e1411SDavid Herrmann 	}
18202c8e1411SDavid Herrmann 
18212c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
18222c8e1411SDavid Herrmann 	if (ret)
18232c8e1411SDavid Herrmann 		goto out_unlock;
18242c8e1411SDavid Herrmann 
18252c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
18262c8e1411SDavid Herrmann 	ret = 0;
18272c8e1411SDavid Herrmann 
18282c8e1411SDavid Herrmann out_unlock:
18292c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18302c8e1411SDavid Herrmann 	return ret;
18312c8e1411SDavid Herrmann }
18322c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
18332c8e1411SDavid Herrmann 
18342c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
18352c8e1411SDavid Herrmann {
18362c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
18372c8e1411SDavid Herrmann 
18382c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18392c8e1411SDavid Herrmann 
1840835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
18412c8e1411SDavid Herrmann 		goto out_unlock;
18422c8e1411SDavid Herrmann 
1843ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
18442c8e1411SDavid Herrmann 	user->remove(conn, user);
18452c8e1411SDavid Herrmann 
18462c8e1411SDavid Herrmann out_unlock:
18472c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18482c8e1411SDavid Herrmann }
18492c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
18502c8e1411SDavid Herrmann 
18512c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
18522c8e1411SDavid Herrmann {
18532c8e1411SDavid Herrmann 	struct l2cap_user *user;
18542c8e1411SDavid Herrmann 
18552c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
18562c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1857ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
18582c8e1411SDavid Herrmann 		user->remove(conn, user);
18592c8e1411SDavid Herrmann 	}
18602c8e1411SDavid Herrmann }
18612c8e1411SDavid Herrmann 
18625d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
18635d3de7dfSVinicius Costa Gomes {
18645d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
18655d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
18665d3de7dfSVinicius Costa Gomes 
18675d3de7dfSVinicius Costa Gomes 	if (!conn)
18685d3de7dfSVinicius Costa Gomes 		return;
18695d3de7dfSVinicius Costa Gomes 
18705d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
18715d3de7dfSVinicius Costa Gomes 
18725d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
18735d3de7dfSVinicius Costa Gomes 
187461a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
18757ab56c3aSJukka Taimisto 
18767ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
18777ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
18787ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
18797ab56c3aSJukka Taimisto 	 */
18807ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
18817ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
188261a939c6SJohan Hedberg 
1883f3d82d0cSJohan Hedberg 	if (work_pending(&conn->id_addr_update_work))
1884f3d82d0cSJohan Hedberg 		cancel_work_sync(&conn->id_addr_update_work);
1885f3d82d0cSJohan Hedberg 
18862c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
18872c8e1411SDavid Herrmann 
1888e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1889e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1890e31fb860SJohan Hedberg 
18913df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
18923df91ea2SAndrei Emeltchenko 
18935d3de7dfSVinicius Costa Gomes 	/* Kill channels */
18945d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
189561d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
18966be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
18976be36555SAndrei Emeltchenko 
18985d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
18996be36555SAndrei Emeltchenko 
190080b98027SGustavo Padovan 		chan->ops->close(chan);
19016c08fc89SManish Mandlik 
19026c08fc89SManish Mandlik 		l2cap_chan_unlock(chan);
190361d6ef3eSMat Martineau 		l2cap_chan_put(chan);
19045d3de7dfSVinicius Costa Gomes 	}
19055d3de7dfSVinicius Costa Gomes 
19063df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
19073df91ea2SAndrei Emeltchenko 
190873d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
190973d80debSLuiz Augusto von Dentz 
19105d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1911127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
19125d3de7dfSVinicius Costa Gomes 
19135d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
19149c903e37SDavid Herrmann 	conn->hchan = NULL;
19159c903e37SDavid Herrmann 	l2cap_conn_put(conn);
19165d3de7dfSVinicius Costa Gomes }
19175d3de7dfSVinicius Costa Gomes 
19189c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
19199c903e37SDavid Herrmann {
19209c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
19219c903e37SDavid Herrmann 
19229c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
19239c903e37SDavid Herrmann 	kfree(conn);
19249c903e37SDavid Herrmann }
19259c903e37SDavid Herrmann 
192651bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
19279c903e37SDavid Herrmann {
19289c903e37SDavid Herrmann 	kref_get(&conn->ref);
192951bb8457SJohan Hedberg 	return conn;
19309c903e37SDavid Herrmann }
19319c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
19329c903e37SDavid Herrmann 
19339c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
19349c903e37SDavid Herrmann {
19359c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
19369c903e37SDavid Herrmann }
19379c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
19389c903e37SDavid Herrmann 
19390a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
19400a708f8fSGustavo F. Padovan 
1941c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
19420a708f8fSGustavo F. Padovan  * Returns closest match.
19430a708f8fSGustavo F. Padovan  */
1944c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1945c2287681SIdo Yariv 						   bdaddr_t *src,
1946bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1947bf20fd4eSJohan Hedberg 						   u8 link_type)
19480a708f8fSGustavo F. Padovan {
194923691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
19500a708f8fSGustavo F. Padovan 
195123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
19520a708f8fSGustavo F. Padovan 
195323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
195489bc500eSGustavo F. Padovan 		if (state && c->state != state)
19550a708f8fSGustavo F. Padovan 			continue;
19560a708f8fSGustavo F. Padovan 
1957bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1958bf20fd4eSJohan Hedberg 			continue;
1959bf20fd4eSJohan Hedberg 
1960bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1961bf20fd4eSJohan Hedberg 			continue;
1962bf20fd4eSJohan Hedberg 
196323691d75SGustavo F. Padovan 		if (c->psm == psm) {
1964c2287681SIdo Yariv 			int src_match, dst_match;
1965c2287681SIdo Yariv 			int src_any, dst_any;
1966c2287681SIdo Yariv 
19670a708f8fSGustavo F. Padovan 			/* Exact match. */
19687eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
19697eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1970c2287681SIdo Yariv 			if (src_match && dst_match) {
1971a24cce14SJohan Hedberg 				l2cap_chan_hold(c);
1972a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
197323691d75SGustavo F. Padovan 				return c;
197423691d75SGustavo F. Padovan 			}
19750a708f8fSGustavo F. Padovan 
19760a708f8fSGustavo F. Padovan 			/* Closest match */
19777eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
19787eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1979c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1980c2287681SIdo Yariv 			    (src_any && dst_any))
198123691d75SGustavo F. Padovan 				c1 = c;
19820a708f8fSGustavo F. Padovan 		}
19830a708f8fSGustavo F. Padovan 	}
19840a708f8fSGustavo F. Padovan 
1985a24cce14SJohan Hedberg 	if (c1)
1986a24cce14SJohan Hedberg 		l2cap_chan_hold(c1);
1987a24cce14SJohan Hedberg 
198823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
19890a708f8fSGustavo F. Padovan 
199023691d75SGustavo F. Padovan 	return c1;
19910a708f8fSGustavo F. Padovan }
19920a708f8fSGustavo F. Padovan 
1993721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
19940a708f8fSGustavo F. Padovan {
1995721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1996721c4181SGustavo F. Padovan 					       monitor_timer.work);
19970a708f8fSGustavo F. Padovan 
1998525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
19990a708f8fSGustavo F. Padovan 
20006be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20016be36555SAndrei Emeltchenko 
200280909e04SMat Martineau 	if (!chan->conn) {
20036be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
20048d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
20050a708f8fSGustavo F. Padovan 		return;
20060a708f8fSGustavo F. Padovan 	}
20070a708f8fSGustavo F. Padovan 
2008401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
20090a708f8fSGustavo F. Padovan 
20106be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20118d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20120a708f8fSGustavo F. Padovan }
20130a708f8fSGustavo F. Padovan 
2014721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20150a708f8fSGustavo F. Padovan {
2016721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2017721c4181SGustavo F. Padovan 					       retrans_timer.work);
20180a708f8fSGustavo F. Padovan 
201949208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20200a708f8fSGustavo F. Padovan 
20216be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20226be36555SAndrei Emeltchenko 
202380909e04SMat Martineau 	if (!chan->conn) {
202480909e04SMat Martineau 		l2cap_chan_unlock(chan);
202580909e04SMat Martineau 		l2cap_chan_put(chan);
202680909e04SMat Martineau 		return;
202780909e04SMat Martineau 	}
20280a708f8fSGustavo F. Padovan 
2029401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20306be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20318d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20320a708f8fSGustavo F. Padovan }
20330a708f8fSGustavo F. Padovan 
2034d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20353733937dSMat Martineau 				 struct sk_buff_head *skbs)
20360a708f8fSGustavo F. Padovan {
20370a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20383733937dSMat Martineau 	struct l2cap_ctrl *control;
20390a708f8fSGustavo F. Padovan 
20403733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20413733937dSMat Martineau 
2042b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2043b99e13adSMat Martineau 		return;
2044b99e13adSMat Martineau 
20453733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20463733937dSMat Martineau 
20473733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20483733937dSMat Martineau 
20493733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20503733937dSMat Martineau 
2051a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2052a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
20533733937dSMat Martineau 
20543733937dSMat Martineau 		control->reqseq = 0;
20553733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20563733937dSMat Martineau 
20573733937dSMat Martineau 		__pack_control(chan, control, skb);
20580a708f8fSGustavo F. Padovan 
205947d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20603733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20613733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20620a708f8fSGustavo F. Padovan 		}
20630a708f8fSGustavo F. Padovan 
20644343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20650a708f8fSGustavo F. Padovan 
2066b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20673733937dSMat Martineau 
2068836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20693733937dSMat Martineau 		chan->frames_sent++;
20700a708f8fSGustavo F. Padovan 	}
20710a708f8fSGustavo F. Padovan }
20720a708f8fSGustavo F. Padovan 
207367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20740a708f8fSGustavo F. Padovan {
20750a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
207618a48e76SMat Martineau 	struct l2cap_ctrl *control;
207718a48e76SMat Martineau 	int sent = 0;
207818a48e76SMat Martineau 
207918a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20800a708f8fSGustavo F. Padovan 
208189bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20820a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20830a708f8fSGustavo F. Padovan 
208494122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
208594122bbeSMat Martineau 		return 0;
208694122bbeSMat Martineau 
2087b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2088b99e13adSMat Martineau 		return 0;
2089b99e13adSMat Martineau 
209018a48e76SMat Martineau 	while (chan->tx_send_head &&
209118a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
209218a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
20930a708f8fSGustavo F. Padovan 
209418a48e76SMat Martineau 		skb = chan->tx_send_head;
20950a708f8fSGustavo F. Padovan 
2096a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2097a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
20980a708f8fSGustavo F. Padovan 
2099e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
210018a48e76SMat Martineau 			control->final = 1;
2101e2ab4353SGustavo F. Padovan 
210218a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
210318a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
210418a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
21050a708f8fSGustavo F. Padovan 
210618a48e76SMat Martineau 		__pack_control(chan, control, skb);
21070a708f8fSGustavo F. Padovan 
210847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
210918a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
211018a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
21110a708f8fSGustavo F. Padovan 		}
21120a708f8fSGustavo F. Padovan 
211318a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
211418a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
211518a48e76SMat Martineau 		 */
211618a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
211718a48e76SMat Martineau 
211818a48e76SMat Martineau 		if (!tx_skb)
211918a48e76SMat Martineau 			break;
21200a708f8fSGustavo F. Padovan 
21211a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21220a708f8fSGustavo F. Padovan 
2123836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21246a026610SGustavo F. Padovan 		chan->unacked_frames++;
21256a026610SGustavo F. Padovan 		chan->frames_sent++;
212618a48e76SMat Martineau 		sent++;
21270a708f8fSGustavo F. Padovan 
212858d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
212958d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21300a708f8fSGustavo F. Padovan 		else
213158d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
213218a48e76SMat Martineau 
213318a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2134b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21350a708f8fSGustavo F. Padovan 	}
21360a708f8fSGustavo F. Padovan 
2137b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2138b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
213918a48e76SMat Martineau 
214018a48e76SMat Martineau 	return sent;
21410a708f8fSGustavo F. Padovan }
21420a708f8fSGustavo F. Padovan 
2143e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2144e1fbd4c1SMat Martineau {
2145e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2146e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2147e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2148e1fbd4c1SMat Martineau 	u16 seq;
2149e1fbd4c1SMat Martineau 
2150e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2151e1fbd4c1SMat Martineau 
2152e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2153e1fbd4c1SMat Martineau 		return;
2154e1fbd4c1SMat Martineau 
2155b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2156b99e13adSMat Martineau 		return;
2157b99e13adSMat Martineau 
2158e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2159e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2160e1fbd4c1SMat Martineau 
2161e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2162e1fbd4c1SMat Martineau 		if (!skb) {
2163e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2164e1fbd4c1SMat Martineau 			       seq);
2165e1fbd4c1SMat Martineau 			continue;
2166e1fbd4c1SMat Martineau 		}
2167e1fbd4c1SMat Martineau 
2168a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
2169a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
2170e1fbd4c1SMat Martineau 
2171e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2172a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2173e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21745e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2175e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2176e1fbd4c1SMat Martineau 			break;
2177e1fbd4c1SMat Martineau 		}
2178e1fbd4c1SMat Martineau 
2179e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2180e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2181e1fbd4c1SMat Martineau 			control.final = 1;
2182e1fbd4c1SMat Martineau 		else
2183e1fbd4c1SMat Martineau 			control.final = 0;
2184e1fbd4c1SMat Martineau 
2185e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2186e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2187e1fbd4c1SMat Martineau 			 * writeable copy
2188e1fbd4c1SMat Martineau 			 */
21898bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2190e1fbd4c1SMat Martineau 		} else {
21918bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2192e1fbd4c1SMat Martineau 		}
2193e1fbd4c1SMat Martineau 
2194e1fbd4c1SMat Martineau 		if (!tx_skb) {
2195e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2196e1fbd4c1SMat Martineau 			break;
2197e1fbd4c1SMat Martineau 		}
2198e1fbd4c1SMat Martineau 
2199e1fbd4c1SMat Martineau 		/* Update skb contents */
2200e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2201e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2202e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2203e1fbd4c1SMat Martineau 		} else {
2204e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2205e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2206e1fbd4c1SMat Martineau 		}
2207e1fbd4c1SMat Martineau 
220813cac152SLukasz Rymanowski 		/* Update FCS */
2209e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
221013cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
221113cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
221213cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
221313cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2214e1fbd4c1SMat Martineau 		}
2215e1fbd4c1SMat Martineau 
2216e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2217e1fbd4c1SMat Martineau 
2218e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2219e1fbd4c1SMat Martineau 
2220e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2221e1fbd4c1SMat Martineau 	}
2222e1fbd4c1SMat Martineau }
2223e1fbd4c1SMat Martineau 
2224f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2225f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2226f80842a8SMat Martineau {
2227f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2228f80842a8SMat Martineau 
2229f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2230f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2231f80842a8SMat Martineau }
2232f80842a8SMat Martineau 
2233d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2234d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2235d2a7ac5dSMat Martineau {
2236e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2237e1fbd4c1SMat Martineau 
2238e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2239e1fbd4c1SMat Martineau 
2240e1fbd4c1SMat Martineau 	if (control->poll)
2241e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2242e1fbd4c1SMat Martineau 
2243e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2244e1fbd4c1SMat Martineau 
2245e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2246e1fbd4c1SMat Martineau 		return;
2247e1fbd4c1SMat Martineau 
2248e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2249e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2250a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2251e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2252e1fbd4c1SMat Martineau 				break;
2253e1fbd4c1SMat Martineau 		}
2254e1fbd4c1SMat Martineau 
2255e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2256e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2257e1fbd4c1SMat Martineau 				break;
2258e1fbd4c1SMat Martineau 
2259e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2260a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2261e1fbd4c1SMat Martineau 		}
2262e1fbd4c1SMat Martineau 
2263e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2264e1fbd4c1SMat Martineau 	}
2265d2a7ac5dSMat Martineau }
2266d2a7ac5dSMat Martineau 
2267b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2268b17e73bbSSzymon Janc {
22690a0aba42SMat Martineau 	struct l2cap_ctrl control;
22700a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22710a0aba42SMat Martineau 					 chan->last_acked_seq);
22720a0aba42SMat Martineau 	int threshold;
22730a0aba42SMat Martineau 
22740a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22750a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22760a0aba42SMat Martineau 
22770a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22780a0aba42SMat Martineau 	control.sframe = 1;
22790a0aba42SMat Martineau 
22800a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22810a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2282b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22830a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22840a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22850a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22860a0aba42SMat Martineau 	} else {
22870a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22880a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22890a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22900a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22910a0aba42SMat Martineau 				frames_to_ack = 0;
22920a0aba42SMat Martineau 		}
22930a0aba42SMat Martineau 
2294c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
22950a0aba42SMat Martineau 		 * Calculate without mul or div
22960a0aba42SMat Martineau 		 */
2297c20f8e35SMat Martineau 		threshold = chan->ack_win;
22980a0aba42SMat Martineau 		threshold += threshold << 1;
22990a0aba42SMat Martineau 		threshold >>= 2;
23000a0aba42SMat Martineau 
2301b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
23020a0aba42SMat Martineau 		       threshold);
23030a0aba42SMat Martineau 
23040a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
23050a0aba42SMat Martineau 			__clear_ack_timer(chan);
23060a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
23070a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
23080a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
23090a0aba42SMat Martineau 			frames_to_ack = 0;
23100a0aba42SMat Martineau 		}
23110a0aba42SMat Martineau 
23120a0aba42SMat Martineau 		if (frames_to_ack)
23130a0aba42SMat Martineau 			__set_ack_timer(chan);
23140a0aba42SMat Martineau 	}
2315b17e73bbSSzymon Janc }
2316b17e73bbSSzymon Janc 
231704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
231804124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
231904124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23200a708f8fSGustavo F. Padovan {
23210952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23220a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
232390338947SGustavo Padovan 	int sent = 0;
23240a708f8fSGustavo F. Padovan 
2325cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
23260a708f8fSGustavo F. Padovan 		return -EFAULT;
23270a708f8fSGustavo F. Padovan 
23280a708f8fSGustavo F. Padovan 	sent += count;
23290a708f8fSGustavo F. Padovan 	len  -= count;
23300a708f8fSGustavo F. Padovan 
23310a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23320a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23330a708f8fSGustavo F. Padovan 	while (len) {
2334fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2335fbe00700SGustavo Padovan 
23360a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23370a708f8fSGustavo F. Padovan 
2338d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
233990338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2340fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2341fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23422f7719ceSAndrei Emeltchenko 
2343fbe00700SGustavo Padovan 		*frag = tmp;
2344fbe00700SGustavo Padovan 
2345cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2346cbbd26b8SAl Viro 				   &msg->msg_iter))
23470a708f8fSGustavo F. Padovan 			return -EFAULT;
23480a708f8fSGustavo F. Padovan 
23490a708f8fSGustavo F. Padovan 		sent += count;
23500a708f8fSGustavo F. Padovan 		len  -= count;
23510a708f8fSGustavo F. Padovan 
23522d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23532d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23542d0ed3d5SGustavo Padovan 
23550a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23560a708f8fSGustavo F. Padovan 	}
23570a708f8fSGustavo F. Padovan 
23580a708f8fSGustavo F. Padovan 	return sent;
23590a708f8fSGustavo F. Padovan }
23600a708f8fSGustavo F. Padovan 
23615e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23628d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
23630a708f8fSGustavo F. Padovan {
23648c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23650a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
236603a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23670a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23680a708f8fSGustavo F. Padovan 
23698d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
23708d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
23710a708f8fSGustavo F. Padovan 
23720a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23732f7719ceSAndrei Emeltchenko 
2374d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
237590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
237690338947SGustavo Padovan 	if (IS_ERR(skb))
237790338947SGustavo Padovan 		return skb;
23780a708f8fSGustavo F. Padovan 
23790a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23804df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2381fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2382daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
238343b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23840a708f8fSGustavo F. Padovan 
23850952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23860a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23870a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23880a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23890a708f8fSGustavo F. Padovan 	}
23900a708f8fSGustavo F. Padovan 	return skb;
23910a708f8fSGustavo F. Padovan }
23920a708f8fSGustavo F. Padovan 
23935e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
23948d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
23950a708f8fSGustavo F. Padovan {
23968c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23970a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2398f2ba7faeSGustavo Padovan 	int err, count;
23990a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24000a708f8fSGustavo F. Padovan 
2401b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24020a708f8fSGustavo F. Padovan 
2403f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
24042f7719ceSAndrei Emeltchenko 
2405d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
240690338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
240790338947SGustavo Padovan 	if (IS_ERR(skb))
240890338947SGustavo Padovan 		return skb;
24090a708f8fSGustavo F. Padovan 
24100a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24114df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2412fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24136ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24140a708f8fSGustavo F. Padovan 
24150952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24160a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24170a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24180a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24190a708f8fSGustavo F. Padovan 	}
24200a708f8fSGustavo F. Padovan 	return skb;
24210a708f8fSGustavo F. Padovan }
24220a708f8fSGustavo F. Padovan 
2423ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2424ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
242594122bbeSMat Martineau 					       u16 sdulen)
24260a708f8fSGustavo F. Padovan {
24278c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24280a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2429e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24300a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24310a708f8fSGustavo F. Padovan 
2432b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24330a708f8fSGustavo F. Padovan 
24340a708f8fSGustavo F. Padovan 	if (!conn)
24350a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24360a708f8fSGustavo F. Padovan 
2437ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2438e4ca6d98SAndrei Emeltchenko 
24390a708f8fSGustavo F. Padovan 	if (sdulen)
244003a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24410a708f8fSGustavo F. Padovan 
244247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
244303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24440a708f8fSGustavo F. Padovan 
24450a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24462f7719ceSAndrei Emeltchenko 
2447d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
244890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
244990338947SGustavo Padovan 	if (IS_ERR(skb))
245090338947SGustavo Padovan 		return skb;
24510a708f8fSGustavo F. Padovan 
24520a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24534df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2454fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24550a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
245688843ab0SAndrei Emeltchenko 
245718a48e76SMat Martineau 	/* Control header is populated later */
245818a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
245918a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
246018a48e76SMat Martineau 	else
246118a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
246288843ab0SAndrei Emeltchenko 
24630a708f8fSGustavo F. Padovan 	if (sdulen)
246403a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24650a708f8fSGustavo F. Padovan 
24660952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24670a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24680a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24690a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24700a708f8fSGustavo F. Padovan 	}
24710a708f8fSGustavo F. Padovan 
2472a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2473a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
24740a708f8fSGustavo F. Padovan 	return skb;
24750a708f8fSGustavo F. Padovan }
24760a708f8fSGustavo F. Padovan 
247794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
247894122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
247994122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24800a708f8fSGustavo F. Padovan {
24810a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
248294122bbeSMat Martineau 	u16 sdu_len;
248394122bbeSMat Martineau 	size_t pdu_len;
248494122bbeSMat Martineau 	u8 sar;
24850a708f8fSGustavo F. Padovan 
2486b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24870a708f8fSGustavo F. Padovan 
248894122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
248994122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
249094122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
249194122bbeSMat Martineau 	 */
249294122bbeSMat Martineau 
249394122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
249494122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
249594122bbeSMat Martineau 
2496a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2497a549574dSMat Martineau 	if (!chan->hs_hcon)
249894122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
249994122bbeSMat Martineau 
250094122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
250135d401dfSGustavo Padovan 	if (chan->fcs)
250235d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
250335d401dfSGustavo Padovan 
2504ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
250594122bbeSMat Martineau 
250694122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
250794122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
250894122bbeSMat Martineau 
250994122bbeSMat Martineau 	if (len <= pdu_len) {
251094122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
251194122bbeSMat Martineau 		sdu_len = 0;
251294122bbeSMat Martineau 		pdu_len = len;
251394122bbeSMat Martineau 	} else {
251494122bbeSMat Martineau 		sar = L2CAP_SAR_START;
251594122bbeSMat Martineau 		sdu_len = len;
251694122bbeSMat Martineau 	}
25170a708f8fSGustavo F. Padovan 
25180a708f8fSGustavo F. Padovan 	while (len > 0) {
251994122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25200a708f8fSGustavo F. Padovan 
25210a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
252294122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25230a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25240a708f8fSGustavo F. Padovan 		}
25250a708f8fSGustavo F. Padovan 
2526a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
252794122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25280a708f8fSGustavo F. Padovan 
252994122bbeSMat Martineau 		len -= pdu_len;
2530069cb270SLukasz Rymanowski 		if (sdu_len)
253194122bbeSMat Martineau 			sdu_len = 0;
253294122bbeSMat Martineau 
253394122bbeSMat Martineau 		if (len <= pdu_len) {
253494122bbeSMat Martineau 			sar = L2CAP_SAR_END;
253594122bbeSMat Martineau 			pdu_len = len;
253694122bbeSMat Martineau 		} else {
253794122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
253894122bbeSMat Martineau 		}
253994122bbeSMat Martineau 	}
254094122bbeSMat Martineau 
2541f0f62799SGustavo Padovan 	return 0;
25420a708f8fSGustavo F. Padovan }
25430a708f8fSGustavo F. Padovan 
2544177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2545177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2546177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2547177f8f2bSJohan Hedberg {
2548177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2549177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2550177f8f2bSJohan Hedberg 	int err, count, hlen;
2551177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2552177f8f2bSJohan Hedberg 
2553177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2554177f8f2bSJohan Hedberg 
2555177f8f2bSJohan Hedberg 	if (!conn)
2556177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2557177f8f2bSJohan Hedberg 
2558177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2559177f8f2bSJohan Hedberg 
2560177f8f2bSJohan Hedberg 	if (sdulen)
2561177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2562177f8f2bSJohan Hedberg 
2563177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2564177f8f2bSJohan Hedberg 
2565d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2566177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2567177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2568177f8f2bSJohan Hedberg 		return skb;
2569177f8f2bSJohan Hedberg 
2570177f8f2bSJohan Hedberg 	/* Create L2CAP header */
25714df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2572177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2573177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2574177f8f2bSJohan Hedberg 
2575177f8f2bSJohan Hedberg 	if (sdulen)
2576177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2577177f8f2bSJohan Hedberg 
2578177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2579177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2580177f8f2bSJohan Hedberg 		kfree_skb(skb);
2581177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2582177f8f2bSJohan Hedberg 	}
2583177f8f2bSJohan Hedberg 
2584177f8f2bSJohan Hedberg 	return skb;
2585177f8f2bSJohan Hedberg }
2586177f8f2bSJohan Hedberg 
2587177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2588177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2589177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2590177f8f2bSJohan Hedberg {
2591177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2592177f8f2bSJohan Hedberg 	size_t pdu_len;
2593177f8f2bSJohan Hedberg 	u16 sdu_len;
2594177f8f2bSJohan Hedberg 
2595177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2596177f8f2bSJohan Hedberg 
2597177f8f2bSJohan Hedberg 	sdu_len = len;
259872c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2599177f8f2bSJohan Hedberg 
2600177f8f2bSJohan Hedberg 	while (len > 0) {
2601177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2602177f8f2bSJohan Hedberg 			pdu_len = len;
2603177f8f2bSJohan Hedberg 
2604177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2605177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2606177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2607177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2608177f8f2bSJohan Hedberg 		}
2609177f8f2bSJohan Hedberg 
2610177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2611177f8f2bSJohan Hedberg 
2612177f8f2bSJohan Hedberg 		len -= pdu_len;
2613177f8f2bSJohan Hedberg 
2614177f8f2bSJohan Hedberg 		if (sdu_len) {
2615177f8f2bSJohan Hedberg 			sdu_len = 0;
2616177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2617177f8f2bSJohan Hedberg 		}
2618177f8f2bSJohan Hedberg 	}
2619177f8f2bSJohan Hedberg 
2620177f8f2bSJohan Hedberg 	return 0;
2621177f8f2bSJohan Hedberg }
2622177f8f2bSJohan Hedberg 
26238a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
26248a505b7fSLuiz Augusto von Dentz {
26258a505b7fSLuiz Augusto von Dentz 	int sent = 0;
26268a505b7fSLuiz Augusto von Dentz 
26278a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
26288a505b7fSLuiz Augusto von Dentz 
26298a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
26308a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
26318a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
26328a505b7fSLuiz Augusto von Dentz 		sent++;
26338a505b7fSLuiz Augusto von Dentz 	}
26348a505b7fSLuiz Augusto von Dentz 
26358a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
26368a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
26378a505b7fSLuiz Augusto von Dentz }
26388a505b7fSLuiz Augusto von Dentz 
26398d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
26409a91a04aSGustavo F. Padovan {
26419a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26429a91a04aSGustavo F. Padovan 	int err;
264394122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26449a91a04aSGustavo F. Padovan 
264531e8ce80SSeung-Woo Kim 	if (!chan->conn)
264631e8ce80SSeung-Woo Kim 		return -ENOTCONN;
264731e8ce80SSeung-Woo Kim 
26489a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2649715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26508d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
26519a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26529a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26539a91a04aSGustavo F. Padovan 
2654ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2655ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2656ede81a2aSAndrzej Kaczmarek 		 */
2657ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2658ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2659ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2660ede81a2aSAndrzej Kaczmarek 		}
2661ede81a2aSAndrzej Kaczmarek 
26629a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26639a91a04aSGustavo F. Padovan 		return len;
26649a91a04aSGustavo F. Padovan 	}
26659a91a04aSGustavo F. Padovan 
26669a91a04aSGustavo F. Padovan 	switch (chan->mode) {
266738319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
266815f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
2669177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2670177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2671177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2672177f8f2bSJohan Hedberg 
2673177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2674177f8f2bSJohan Hedberg 
2675177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2676177f8f2bSJohan Hedberg 
2677177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2678177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2679177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2680177f8f2bSJohan Hedberg 		}
2681177f8f2bSJohan Hedberg 
2682177f8f2bSJohan Hedberg 		if (err)
2683177f8f2bSJohan Hedberg 			return err;
2684177f8f2bSJohan Hedberg 
2685177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2686177f8f2bSJohan Hedberg 
26878a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2688177f8f2bSJohan Hedberg 
2689177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2690177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2691177f8f2bSJohan Hedberg 
2692177f8f2bSJohan Hedberg 		err = len;
2693177f8f2bSJohan Hedberg 
2694177f8f2bSJohan Hedberg 		break;
2695177f8f2bSJohan Hedberg 
2696fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
26979a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
26989a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
26999a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
27009a91a04aSGustavo F. Padovan 
27019a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
27028d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
27039a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
27049a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
27059a91a04aSGustavo F. Padovan 
2706ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2707ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2708ede81a2aSAndrzej Kaczmarek 		 */
2709ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2710ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2711ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2712ede81a2aSAndrzej Kaczmarek 		}
2713ede81a2aSAndrzej Kaczmarek 
27149a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
27159a91a04aSGustavo F. Padovan 		err = len;
27169a91a04aSGustavo F. Padovan 		break;
27179a91a04aSGustavo F. Padovan 
27189a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27199a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
272094122bbeSMat Martineau 		/* Check outgoing MTU */
272194122bbeSMat Martineau 		if (len > chan->omtu) {
272294122bbeSMat Martineau 			err = -EMSGSIZE;
27239a91a04aSGustavo F. Padovan 			break;
27249a91a04aSGustavo F. Padovan 		}
27259a91a04aSGustavo F. Padovan 
272694122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
272794122bbeSMat Martineau 
272894122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
272994122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
273094122bbeSMat Martineau 		 * allocation.
273194122bbeSMat Martineau 		 */
273294122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
273394122bbeSMat Martineau 
273494122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
273594122bbeSMat Martineau 		 * check that it is still connected.
273694122bbeSMat Martineau 		 */
273794122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
273894122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
273994122bbeSMat Martineau 			err = -ENOTCONN;
27409a91a04aSGustavo F. Padovan 		}
27419a91a04aSGustavo F. Padovan 
274294122bbeSMat Martineau 		if (err)
274394122bbeSMat Martineau 			break;
274494122bbeSMat Martineau 
27453733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2746d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27473733937dSMat Martineau 		else
2748d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
274994122bbeSMat Martineau 
27509a91a04aSGustavo F. Padovan 		err = len;
27519a91a04aSGustavo F. Padovan 
275294122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
275394122bbeSMat Martineau 		 * seg_queue and need to be purged.
275494122bbeSMat Martineau 		 */
275594122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27569a91a04aSGustavo F. Padovan 		break;
27579a91a04aSGustavo F. Padovan 
27589a91a04aSGustavo F. Padovan 	default:
27599a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27609a91a04aSGustavo F. Padovan 		err = -EBADFD;
27619a91a04aSGustavo F. Padovan 	}
27629a91a04aSGustavo F. Padovan 
27639a91a04aSGustavo F. Padovan 	return err;
27649a91a04aSGustavo F. Padovan }
27656b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
27669a91a04aSGustavo F. Padovan 
2767d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2768d2a7ac5dSMat Martineau {
2769bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2770bed68bdeSMat Martineau 	u16 seq;
2771bed68bdeSMat Martineau 
2772b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2773bed68bdeSMat Martineau 
2774bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2775bed68bdeSMat Martineau 	control.sframe = 1;
2776bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2777bed68bdeSMat Martineau 
2778bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2779bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2780bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2781bed68bdeSMat Martineau 			control.reqseq = seq;
2782bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2783bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2784bed68bdeSMat Martineau 		}
2785bed68bdeSMat Martineau 	}
2786bed68bdeSMat Martineau 
2787bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2788d2a7ac5dSMat Martineau }
2789d2a7ac5dSMat Martineau 
2790d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2791d2a7ac5dSMat Martineau {
2792bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2793bed68bdeSMat Martineau 
2794bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2795bed68bdeSMat Martineau 
2796bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2797bed68bdeSMat Martineau 		return;
2798bed68bdeSMat Martineau 
2799bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2800bed68bdeSMat Martineau 	control.sframe = 1;
2801bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2802bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2803bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2804d2a7ac5dSMat Martineau }
2805d2a7ac5dSMat Martineau 
2806d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2807d2a7ac5dSMat Martineau {
2808bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2809bed68bdeSMat Martineau 	u16 initial_head;
2810bed68bdeSMat Martineau 	u16 seq;
2811bed68bdeSMat Martineau 
2812b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2813bed68bdeSMat Martineau 
2814bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2815bed68bdeSMat Martineau 	control.sframe = 1;
2816bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2817bed68bdeSMat Martineau 
2818bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2819bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2820bed68bdeSMat Martineau 
2821bed68bdeSMat Martineau 	do {
2822bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2823bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2824bed68bdeSMat Martineau 			break;
2825bed68bdeSMat Martineau 
2826bed68bdeSMat Martineau 		control.reqseq = seq;
2827bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2828bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2829bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2830d2a7ac5dSMat Martineau }
2831d2a7ac5dSMat Martineau 
2832608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2833608bcc6dSMat Martineau {
2834608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2835608bcc6dSMat Martineau 	u16 ackseq;
2836608bcc6dSMat Martineau 
2837b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2838608bcc6dSMat Martineau 
2839608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2840608bcc6dSMat Martineau 		return;
2841608bcc6dSMat Martineau 
2842b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2843608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2844608bcc6dSMat Martineau 
2845608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2846608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2847608bcc6dSMat Martineau 
2848608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2849608bcc6dSMat Martineau 		if (acked_skb) {
2850608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2851608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2852608bcc6dSMat Martineau 			chan->unacked_frames--;
2853608bcc6dSMat Martineau 		}
2854608bcc6dSMat Martineau 	}
2855608bcc6dSMat Martineau 
2856608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2857608bcc6dSMat Martineau 
2858608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2859608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2860608bcc6dSMat Martineau 
2861b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2862608bcc6dSMat Martineau }
2863608bcc6dSMat Martineau 
2864608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2865608bcc6dSMat Martineau {
2866608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2867608bcc6dSMat Martineau 
2868608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2869608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2870608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2871608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2872608bcc6dSMat Martineau }
2873608bcc6dSMat Martineau 
2874d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2875608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2876608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2877608bcc6dSMat Martineau {
2878608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2879608bcc6dSMat Martineau 	       event);
2880608bcc6dSMat Martineau 
2881608bcc6dSMat Martineau 	switch (event) {
2882608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2883608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2884608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2885608bcc6dSMat Martineau 
2886608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2887608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2888608bcc6dSMat Martineau 		break;
2889608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2890608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2891608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2892608bcc6dSMat Martineau 
2893608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2894608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2895608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2896608bcc6dSMat Martineau 			 */
2897608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2898608bcc6dSMat Martineau 		}
2899608bcc6dSMat Martineau 
2900608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2901608bcc6dSMat Martineau 
2902608bcc6dSMat Martineau 		break;
2903608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2904608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2905608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2906608bcc6dSMat Martineau 
2907608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2908608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2909608bcc6dSMat Martineau 
2910608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2911608bcc6dSMat Martineau 			local_control.sframe = 1;
2912608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2913608bcc6dSMat Martineau 			local_control.poll = 1;
2914608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2915a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2916608bcc6dSMat Martineau 
2917608bcc6dSMat Martineau 			chan->retry_count = 1;
2918608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2919608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2920608bcc6dSMat Martineau 		}
2921608bcc6dSMat Martineau 		break;
2922608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2923608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2924608bcc6dSMat Martineau 		break;
2925608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2926608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2927608bcc6dSMat Martineau 		chan->retry_count = 1;
2928608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2929608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2930608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2931608bcc6dSMat Martineau 		break;
2932608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2933608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2934608bcc6dSMat Martineau 		chan->retry_count = 1;
2935608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2936608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2937608bcc6dSMat Martineau 		break;
2938608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2939608bcc6dSMat Martineau 		/* Nothing to process */
2940608bcc6dSMat Martineau 		break;
2941608bcc6dSMat Martineau 	default:
2942608bcc6dSMat Martineau 		break;
2943608bcc6dSMat Martineau 	}
2944608bcc6dSMat Martineau }
2945608bcc6dSMat Martineau 
2946d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2947608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2948608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2949608bcc6dSMat Martineau {
2950608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2951608bcc6dSMat Martineau 	       event);
2952608bcc6dSMat Martineau 
2953608bcc6dSMat Martineau 	switch (event) {
2954608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2955608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2956608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2957608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2958608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2959608bcc6dSMat Martineau 		break;
2960608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2961608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2962608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2963608bcc6dSMat Martineau 
2964608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2965608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2966608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2967608bcc6dSMat Martineau 			 */
2968608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2969608bcc6dSMat Martineau 		}
2970608bcc6dSMat Martineau 
2971608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2972608bcc6dSMat Martineau 
2973608bcc6dSMat Martineau 		break;
2974608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2975608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2976608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2977608bcc6dSMat Martineau 
2978608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2979608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2980608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2981608bcc6dSMat Martineau 			local_control.sframe = 1;
2982608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2983608bcc6dSMat Martineau 			local_control.poll = 1;
2984608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2985a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2986608bcc6dSMat Martineau 
2987608bcc6dSMat Martineau 			chan->retry_count = 1;
2988608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2989608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2990608bcc6dSMat Martineau 		}
2991608bcc6dSMat Martineau 		break;
2992608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2993608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
299419186c7bSGustavo A. R. Silva 		fallthrough;
2995608bcc6dSMat Martineau 
2996608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2997608bcc6dSMat Martineau 		if (control && control->final) {
2998608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2999608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
3000608bcc6dSMat Martineau 				__set_retrans_timer(chan);
3001608bcc6dSMat Martineau 			chan->retry_count = 0;
3002608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
3003608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
3004608bcc6dSMat Martineau 		}
3005608bcc6dSMat Martineau 		break;
3006608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
3007608bcc6dSMat Martineau 		/* Ignore */
3008608bcc6dSMat Martineau 		break;
3009608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
3010608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
3011608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
3012608bcc6dSMat Martineau 			__set_monitor_timer(chan);
3013608bcc6dSMat Martineau 			chan->retry_count++;
3014608bcc6dSMat Martineau 		} else {
30155e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
3016608bcc6dSMat Martineau 		}
3017608bcc6dSMat Martineau 		break;
3018608bcc6dSMat Martineau 	default:
3019608bcc6dSMat Martineau 		break;
3020608bcc6dSMat Martineau 	}
3021608bcc6dSMat Martineau }
3022608bcc6dSMat Martineau 
3023d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
3024608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
3025608bcc6dSMat Martineau {
3026608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
3027608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
3028608bcc6dSMat Martineau 
3029608bcc6dSMat Martineau 	switch (chan->tx_state) {
3030608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3031d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3032608bcc6dSMat Martineau 		break;
3033608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3034d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3035608bcc6dSMat Martineau 		break;
3036608bcc6dSMat Martineau 	default:
3037608bcc6dSMat Martineau 		/* Ignore event */
3038608bcc6dSMat Martineau 		break;
3039608bcc6dSMat Martineau 	}
3040608bcc6dSMat Martineau }
3041608bcc6dSMat Martineau 
30424b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30434b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30444b51dae9SMat Martineau {
30454b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3046401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30474b51dae9SMat Martineau }
30484b51dae9SMat Martineau 
3049f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3050f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3051f80842a8SMat Martineau {
3052f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3053401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3054f80842a8SMat Martineau }
3055f80842a8SMat Martineau 
30560a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30570a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30580a708f8fSGustavo F. Padovan {
30590a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
306048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30610a708f8fSGustavo F. Padovan 
30620a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30630a708f8fSGustavo F. Padovan 
30643df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30653d57dc68SGustavo F. Padovan 
30663df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3067715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30680a708f8fSGustavo F. Padovan 			continue;
30690a708f8fSGustavo F. Padovan 
30707f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
3071a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
30720a708f8fSGustavo F. Padovan 			continue;
30737f5396a7SGustavo Padovan 
30748bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30750a708f8fSGustavo F. Padovan 		if (!nskb)
30760a708f8fSGustavo F. Padovan 			continue;
307780b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30780a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30790a708f8fSGustavo F. Padovan 	}
30803d57dc68SGustavo F. Padovan 
30813df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30820a708f8fSGustavo F. Padovan }
30830a708f8fSGustavo F. Padovan 
30840a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3085b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3086b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30870a708f8fSGustavo F. Padovan {
30880a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30890a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30900a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30910a708f8fSGustavo F. Padovan 	int len, count;
30920a708f8fSGustavo F. Padovan 
3093b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30940a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
30950a708f8fSGustavo F. Padovan 
3096300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3097300b962eSAnderson Lizardo 		return NULL;
3098300b962eSAnderson Lizardo 
30990a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
31000a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
31010a708f8fSGustavo F. Padovan 
31028bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
31030a708f8fSGustavo F. Padovan 	if (!skb)
31040a708f8fSGustavo F. Padovan 		return NULL;
31050a708f8fSGustavo F. Padovan 
31064df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
31070a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
31083300d9a9SClaudio Takahasi 
31093300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3110dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
31113300d9a9SClaudio Takahasi 	else
3112dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
31130a708f8fSGustavo F. Padovan 
31144df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
31150a708f8fSGustavo F. Padovan 	cmd->code  = code;
31160a708f8fSGustavo F. Padovan 	cmd->ident = ident;
31170a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
31180a708f8fSGustavo F. Padovan 
31190a708f8fSGustavo F. Padovan 	if (dlen) {
31200a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
312159ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
31220a708f8fSGustavo F. Padovan 		data += count;
31230a708f8fSGustavo F. Padovan 	}
31240a708f8fSGustavo F. Padovan 
31250a708f8fSGustavo F. Padovan 	len -= skb->len;
31260a708f8fSGustavo F. Padovan 
31270a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
31280a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31290a708f8fSGustavo F. Padovan 	while (len) {
31300a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31310a708f8fSGustavo F. Padovan 
31328bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31330a708f8fSGustavo F. Padovan 		if (!*frag)
31340a708f8fSGustavo F. Padovan 			goto fail;
31350a708f8fSGustavo F. Padovan 
313659ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
31370a708f8fSGustavo F. Padovan 
31380a708f8fSGustavo F. Padovan 		len  -= count;
31390a708f8fSGustavo F. Padovan 		data += count;
31400a708f8fSGustavo F. Padovan 
31410a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31420a708f8fSGustavo F. Padovan 	}
31430a708f8fSGustavo F. Padovan 
31440a708f8fSGustavo F. Padovan 	return skb;
31450a708f8fSGustavo F. Padovan 
31460a708f8fSGustavo F. Padovan fail:
31470a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31480a708f8fSGustavo F. Padovan 	return NULL;
31490a708f8fSGustavo F. Padovan }
31500a708f8fSGustavo F. Padovan 
31512d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31522d792818SGustavo Padovan 				     unsigned long *val)
31530a708f8fSGustavo F. Padovan {
31540a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31550a708f8fSGustavo F. Padovan 	int len;
31560a708f8fSGustavo F. Padovan 
31570a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31580a708f8fSGustavo F. Padovan 	*ptr += len;
31590a708f8fSGustavo F. Padovan 
31600a708f8fSGustavo F. Padovan 	*type = opt->type;
31610a708f8fSGustavo F. Padovan 	*olen = opt->len;
31620a708f8fSGustavo F. Padovan 
31630a708f8fSGustavo F. Padovan 	switch (opt->len) {
31640a708f8fSGustavo F. Padovan 	case 1:
31650a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31660a708f8fSGustavo F. Padovan 		break;
31670a708f8fSGustavo F. Padovan 
31680a708f8fSGustavo F. Padovan 	case 2:
31690a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31700a708f8fSGustavo F. Padovan 		break;
31710a708f8fSGustavo F. Padovan 
31720a708f8fSGustavo F. Padovan 	case 4:
31730a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31740a708f8fSGustavo F. Padovan 		break;
31750a708f8fSGustavo F. Padovan 
31760a708f8fSGustavo F. Padovan 	default:
31770a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31780a708f8fSGustavo F. Padovan 		break;
31790a708f8fSGustavo F. Padovan 	}
31800a708f8fSGustavo F. Padovan 
3181b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31820a708f8fSGustavo F. Padovan 	return len;
31830a708f8fSGustavo F. Padovan }
31840a708f8fSGustavo F. Padovan 
3185e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
31860a708f8fSGustavo F. Padovan {
31870a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31880a708f8fSGustavo F. Padovan 
3189b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31900a708f8fSGustavo F. Padovan 
3191e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3192e860d2c9SBen Seri 		return;
3193e860d2c9SBen Seri 
31940a708f8fSGustavo F. Padovan 	opt->type = type;
31950a708f8fSGustavo F. Padovan 	opt->len  = len;
31960a708f8fSGustavo F. Padovan 
31970a708f8fSGustavo F. Padovan 	switch (len) {
31980a708f8fSGustavo F. Padovan 	case 1:
31990a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
32000a708f8fSGustavo F. Padovan 		break;
32010a708f8fSGustavo F. Padovan 
32020a708f8fSGustavo F. Padovan 	case 2:
32030a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
32040a708f8fSGustavo F. Padovan 		break;
32050a708f8fSGustavo F. Padovan 
32060a708f8fSGustavo F. Padovan 	case 4:
32070a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
32080a708f8fSGustavo F. Padovan 		break;
32090a708f8fSGustavo F. Padovan 
32100a708f8fSGustavo F. Padovan 	default:
32110a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
32120a708f8fSGustavo F. Padovan 		break;
32130a708f8fSGustavo F. Padovan 	}
32140a708f8fSGustavo F. Padovan 
32150a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
32160a708f8fSGustavo F. Padovan }
32170a708f8fSGustavo F. Padovan 
3218e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3219f89cef09SAndrei Emeltchenko {
3220f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3221f89cef09SAndrei Emeltchenko 
3222f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3223f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3224f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3225f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3226f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3227f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3228dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3229dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3230f89cef09SAndrei Emeltchenko 		break;
3231f89cef09SAndrei Emeltchenko 
3232f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3233f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3234f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3235f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3236f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3237f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3238f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3239f89cef09SAndrei Emeltchenko 		break;
3240f89cef09SAndrei Emeltchenko 
3241f89cef09SAndrei Emeltchenko 	default:
3242f89cef09SAndrei Emeltchenko 		return;
3243f89cef09SAndrei Emeltchenko 	}
3244f89cef09SAndrei Emeltchenko 
3245f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3246e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3247f89cef09SAndrei Emeltchenko }
3248f89cef09SAndrei Emeltchenko 
3249721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32500a708f8fSGustavo F. Padovan {
3251721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3252721c4181SGustavo F. Padovan 					       ack_timer.work);
32530362520bSMat Martineau 	u16 frames_to_ack;
32540a708f8fSGustavo F. Padovan 
32552fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32562fb9b3d4SGustavo F. Padovan 
32576be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32586be36555SAndrei Emeltchenko 
32590362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32600362520bSMat Martineau 				     chan->last_acked_seq);
32610362520bSMat Martineau 
32620362520bSMat Martineau 	if (frames_to_ack)
32630362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32646be36555SAndrei Emeltchenko 
32656be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
326609bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32670a708f8fSGustavo F. Padovan }
32680a708f8fSGustavo F. Padovan 
3269466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32700a708f8fSGustavo F. Padovan {
32713c588192SMat Martineau 	int err;
32723c588192SMat Martineau 
3273105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3274105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
327542e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32766a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
327742e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32786a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3279105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3280105bdf9eSMat Martineau 	chan->sdu = NULL;
3281105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3282105bdf9eSMat Martineau 	chan->sdu_len = 0;
3283105bdf9eSMat Martineau 
3284d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3285d34c34fbSMat Martineau 
32866ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32876ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
328808333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
328908333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
329008333283SMat Martineau 
3291105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3292105bdf9eSMat Martineau 		return 0;
3293105bdf9eSMat Martineau 
3294105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3295105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
32960a708f8fSGustavo F. Padovan 
3297721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3298721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3299721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
33000a708f8fSGustavo F. Padovan 
3301f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
33020a708f8fSGustavo F. Padovan 
33033c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
33043c588192SMat Martineau 	if (err < 0)
33053c588192SMat Martineau 		return err;
33063c588192SMat Martineau 
33079dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
33089dc9affcSMat Martineau 	if (err < 0)
33099dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
33109dc9affcSMat Martineau 
33119dc9affcSMat Martineau 	return err;
33120a708f8fSGustavo F. Padovan }
33130a708f8fSGustavo F. Padovan 
33140a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
33150a708f8fSGustavo F. Padovan {
33160a708f8fSGustavo F. Padovan 	switch (mode) {
33170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33190a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
33200a708f8fSGustavo F. Padovan 			return mode;
332119186c7bSGustavo A. R. Silva 		fallthrough;
33220a708f8fSGustavo F. Padovan 	default:
33230a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
33240a708f8fSGustavo F. Padovan 	}
33250a708f8fSGustavo F. Padovan }
33260a708f8fSGustavo F. Padovan 
3327848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
33286327eb98SAndrei Emeltchenko {
33290bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33300bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
33316327eb98SAndrei Emeltchenko }
33326327eb98SAndrei Emeltchenko 
3333848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3334f89cef09SAndrei Emeltchenko {
33350bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33360bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3337f89cef09SAndrei Emeltchenko }
3338f89cef09SAndrei Emeltchenko 
333936c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
334036c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
334136c86c85SMat Martineau {
33426ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
334336c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
334436c86c85SMat Martineau 
334536c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
334636c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
334736c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
334836c86c85SMat Martineau 		 * controllers is 10 seconds.
334936c86c85SMat Martineau 		 *
335036c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
335136c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
335236c86c85SMat Martineau 		 * will result in a timeout that meets the above
335336c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
335436c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
335536c86c85SMat Martineau 		 */
335636c86c85SMat Martineau 
335736c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
335836c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
335936c86c85SMat Martineau 
336036c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
336136c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
336236c86c85SMat Martineau 		 * controller.
336336c86c85SMat Martineau 		 */
336436c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
336536c86c85SMat Martineau 
336636c86c85SMat Martineau 		if (ertm_to > 0xffff)
336736c86c85SMat Martineau 			ertm_to = 0xffff;
336836c86c85SMat Martineau 
336936c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
337036c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
337136c86c85SMat Martineau 	} else {
3372dcf4adbfSJoe Perches 		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3373dcf4adbfSJoe Perches 		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
337436c86c85SMat Martineau 	}
337536c86c85SMat Martineau }
337636c86c85SMat Martineau 
33776327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33786327eb98SAndrei Emeltchenko {
33796327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3380848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33816327eb98SAndrei Emeltchenko 		/* use extended control field */
33826327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3383836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3384836be934SAndrei Emeltchenko 	} else {
33856327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33866327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3387836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3388836be934SAndrei Emeltchenko 	}
3389c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33906327eb98SAndrei Emeltchenko }
33916327eb98SAndrei Emeltchenko 
33924b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
33934b6e228eSLuiz Augusto von Dentz {
33944b6e228eSLuiz Augusto von Dentz 	struct hci_conn *conn = chan->conn->hcon;
33954b6e228eSLuiz Augusto von Dentz 
33964b6e228eSLuiz Augusto von Dentz 	chan->imtu = L2CAP_DEFAULT_MIN_MTU;
33974b6e228eSLuiz Augusto von Dentz 
33984b6e228eSLuiz Augusto von Dentz 	/* The 2-DH1 packet has between 2 and 56 information bytes
33994b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34004b6e228eSLuiz Augusto von Dentz 	 */
34014b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH1))
34024b6e228eSLuiz Augusto von Dentz 		chan->imtu = 54;
34034b6e228eSLuiz Augusto von Dentz 
34044b6e228eSLuiz Augusto von Dentz 	/* The 3-DH1 packet has between 2 and 85 information bytes
34054b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34064b6e228eSLuiz Augusto von Dentz 	 */
34074b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH1))
34084b6e228eSLuiz Augusto von Dentz 		chan->imtu = 83;
34094b6e228eSLuiz Augusto von Dentz 
34104b6e228eSLuiz Augusto von Dentz 	/* The 2-DH3 packet has between 2 and 369 information bytes
34114b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34124b6e228eSLuiz Augusto von Dentz 	 */
34134b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH3))
34144b6e228eSLuiz Augusto von Dentz 		chan->imtu = 367;
34154b6e228eSLuiz Augusto von Dentz 
34164b6e228eSLuiz Augusto von Dentz 	/* The 3-DH3 packet has between 2 and 554 information bytes
34174b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34184b6e228eSLuiz Augusto von Dentz 	 */
34194b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH3))
34204b6e228eSLuiz Augusto von Dentz 		chan->imtu = 552;
34214b6e228eSLuiz Augusto von Dentz 
34224b6e228eSLuiz Augusto von Dentz 	/* The 2-DH5 packet has between 2 and 681 information bytes
34234b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34244b6e228eSLuiz Augusto von Dentz 	 */
34254b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH5))
34264b6e228eSLuiz Augusto von Dentz 		chan->imtu = 679;
34274b6e228eSLuiz Augusto von Dentz 
34284b6e228eSLuiz Augusto von Dentz 	/* The 3-DH5 packet has between 2 and 1023 information bytes
34294b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34304b6e228eSLuiz Augusto von Dentz 	 */
34314b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH5))
34324b6e228eSLuiz Augusto von Dentz 		chan->imtu = 1021;
34334b6e228eSLuiz Augusto von Dentz }
34344b6e228eSLuiz Augusto von Dentz 
3435e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
34360a708f8fSGustavo F. Padovan {
34370a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
34380c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
34390a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3440e860d2c9SBen Seri 	void *endptr = data + data_size;
3441c8f79162SAndrei Emeltchenko 	u16 size;
34420a708f8fSGustavo F. Padovan 
344349208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
34440a708f8fSGustavo F. Padovan 
344573ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
34460a708f8fSGustavo F. Padovan 		goto done;
34470a708f8fSGustavo F. Padovan 
34480c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34490a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34500a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3451c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
34520a708f8fSGustavo F. Padovan 			break;
34530a708f8fSGustavo F. Padovan 
3454848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3455f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3456f89cef09SAndrei Emeltchenko 
345719186c7bSGustavo A. R. Silva 		fallthrough;
34580a708f8fSGustavo F. Padovan 	default:
34598c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
34600a708f8fSGustavo F. Padovan 		break;
34610a708f8fSGustavo F. Padovan 	}
34620a708f8fSGustavo F. Padovan 
34630a708f8fSGustavo F. Padovan done:
34644b6e228eSLuiz Augusto von Dentz 	if (chan->imtu != L2CAP_DEFAULT_MTU) {
34654b6e228eSLuiz Augusto von Dentz 		if (!chan->imtu)
34664b6e228eSLuiz Augusto von Dentz 			l2cap_mtu_auto(chan);
34674b6e228eSLuiz Augusto von Dentz 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
34684b6e228eSLuiz Augusto von Dentz 				   endptr - ptr);
34694b6e228eSLuiz Augusto von Dentz 	}
34700a708f8fSGustavo F. Padovan 
34710c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34720a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
34736fea7ad1SMarcel Holtmann 		if (disable_ertm)
34746fea7ad1SMarcel Holtmann 			break;
34756fea7ad1SMarcel Holtmann 
34768c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
34778c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
34780a708f8fSGustavo F. Padovan 			break;
34790a708f8fSGustavo F. Padovan 
34800a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
34810a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34820a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34830a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34840a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34850a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34860a708f8fSGustavo F. Padovan 
34870a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3488e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34890a708f8fSGustavo F. Padovan 		break;
34900a708f8fSGustavo F. Padovan 
34910a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34920a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
349347d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
349436c86c85SMat Martineau 
349536c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3496c8f79162SAndrei Emeltchenko 
3497c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34982d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3499c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3500c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35010a708f8fSGustavo F. Padovan 
35026327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
35036327eb98SAndrei Emeltchenko 
35046327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
35056327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
35060a708f8fSGustavo F. Padovan 
35070a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3508e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35090a708f8fSGustavo F. Padovan 
3510f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3511e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3512f89cef09SAndrei Emeltchenko 
35136327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
35146327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3515e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
351660918918SAndrei Emeltchenko 
351760918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
351860918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3519f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
352060918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
352160918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3522e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
352360918918SAndrei Emeltchenko 			}
35240a708f8fSGustavo F. Padovan 		break;
35250a708f8fSGustavo F. Padovan 
35260a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3527273759e2SMat Martineau 		l2cap_txwin_setup(chan);
35280a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
35290a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
35300a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
35310a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
35320a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3533c8f79162SAndrei Emeltchenko 
3534c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
35352d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3536c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3537c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35380a708f8fSGustavo F. Padovan 
35390a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3540e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35410a708f8fSGustavo F. Padovan 
3542f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3543e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3544f89cef09SAndrei Emeltchenko 
354560918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
354647d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3547f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
354847d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
354960918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3550e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
35510a708f8fSGustavo F. Padovan 			}
35520a708f8fSGustavo F. Padovan 		break;
35530a708f8fSGustavo F. Padovan 	}
35540a708f8fSGustavo F. Padovan 
3555fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3556dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
35570a708f8fSGustavo F. Padovan 
35580a708f8fSGustavo F. Padovan 	return ptr - data;
35590a708f8fSGustavo F. Padovan }
35600a708f8fSGustavo F. Padovan 
3561e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
35620a708f8fSGustavo F. Padovan {
35630a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
35640a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3565e860d2c9SBen Seri 	void *endptr = data + data_size;
356673ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
356773ffa904SGustavo F. Padovan 	int len = chan->conf_len;
35680a708f8fSGustavo F. Padovan 	int type, hint, olen;
35690a708f8fSGustavo F. Padovan 	unsigned long val;
35700a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
357142dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
357242dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
35730a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
35740a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3575c8f79162SAndrei Emeltchenko 	u16 size;
35760a708f8fSGustavo F. Padovan 
357773ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
35780a708f8fSGustavo F. Padovan 
35790a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35800a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
35817c9cbd0bSMarcel Holtmann 		if (len < 0)
35827c9cbd0bSMarcel Holtmann 			break;
35830a708f8fSGustavo F. Padovan 
35840a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
35850a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
35860a708f8fSGustavo F. Padovan 
35870a708f8fSGustavo F. Padovan 		switch (type) {
35880a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3589af3d5d1cSMarcel Holtmann 			if (olen != 2)
3590af3d5d1cSMarcel Holtmann 				break;
35910a708f8fSGustavo F. Padovan 			mtu = val;
35920a708f8fSGustavo F. Padovan 			break;
35930a708f8fSGustavo F. Padovan 
35940a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3595af3d5d1cSMarcel Holtmann 			if (olen != 2)
3596af3d5d1cSMarcel Holtmann 				break;
35970c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35980a708f8fSGustavo F. Padovan 			break;
35990a708f8fSGustavo F. Padovan 
36000a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
36010a708f8fSGustavo F. Padovan 			break;
36020a708f8fSGustavo F. Padovan 
36030a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3604af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3605af3d5d1cSMarcel Holtmann 				break;
36060a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
36070a708f8fSGustavo F. Padovan 			break;
36080a708f8fSGustavo F. Padovan 
36090a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3610af3d5d1cSMarcel Holtmann 			if (olen != 1)
3611af3d5d1cSMarcel Holtmann 				break;
36120a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3613f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
361442dceae2SAndrei Emeltchenko 			break;
36150a708f8fSGustavo F. Padovan 
361642dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3617af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3618af3d5d1cSMarcel Holtmann 				break;
361942dceae2SAndrei Emeltchenko 			remote_efs = 1;
362042dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
36210a708f8fSGustavo F. Padovan 			break;
36220a708f8fSGustavo F. Padovan 
36236327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3624af3d5d1cSMarcel Holtmann 			if (olen != 2)
3625af3d5d1cSMarcel Holtmann 				break;
36260bd49fc7SJohan Hedberg 			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
36276327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
36286327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
36296327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3630836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
36316327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
36320a708f8fSGustavo F. Padovan 			break;
36330a708f8fSGustavo F. Padovan 
36340a708f8fSGustavo F. Padovan 		default:
36350a708f8fSGustavo F. Padovan 			if (hint)
36360a708f8fSGustavo F. Padovan 				break;
36370a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
36385b8ec15dSJimmy Wahlberg 			l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
36390a708f8fSGustavo F. Padovan 			break;
36400a708f8fSGustavo F. Padovan 		}
36410a708f8fSGustavo F. Padovan 	}
36420a708f8fSGustavo F. Padovan 
364373ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
36440a708f8fSGustavo F. Padovan 		goto done;
36450a708f8fSGustavo F. Padovan 
36460c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
36470a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
36480a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3649c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
36500c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
36518c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
36520a708f8fSGustavo F. Padovan 			break;
36530a708f8fSGustavo F. Padovan 		}
36540a708f8fSGustavo F. Padovan 
365542dceae2SAndrei Emeltchenko 		if (remote_efs) {
3656848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
365742dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
365842dceae2SAndrei Emeltchenko 			else
365942dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
366042dceae2SAndrei Emeltchenko 		}
366142dceae2SAndrei Emeltchenko 
36620c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
36630a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36640a708f8fSGustavo F. Padovan 
36650a708f8fSGustavo F. Padovan 		break;
36660a708f8fSGustavo F. Padovan 	}
36670a708f8fSGustavo F. Padovan 
36680a708f8fSGustavo F. Padovan done:
36690c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
36700a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
36710c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
36720a708f8fSGustavo F. Padovan 
367373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
36740a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36750a708f8fSGustavo F. Padovan 
36762d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3677e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
36780a708f8fSGustavo F. Padovan 	}
36790a708f8fSGustavo F. Padovan 
36800a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
36810a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
36820a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
36830a708f8fSGustavo F. Padovan 
36840a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
36850a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36860a708f8fSGustavo F. Padovan 		else {
36870c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3688c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
36890a708f8fSGustavo F. Padovan 		}
3690e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
36910a708f8fSGustavo F. Padovan 
369242dceae2SAndrei Emeltchenko 		if (remote_efs) {
369342dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
369442dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
369542dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
369642dceae2SAndrei Emeltchenko 
369742dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
369842dceae2SAndrei Emeltchenko 
369942dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
370042dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
370142dceae2SAndrei Emeltchenko 
370242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
370342dceae2SAndrei Emeltchenko 						   sizeof(efs),
3704e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
37050e8b207eSAndrei Emeltchenko 			} else {
37063e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
37070e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
37080e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
370942dceae2SAndrei Emeltchenko 			}
371042dceae2SAndrei Emeltchenko 		}
371142dceae2SAndrei Emeltchenko 
37120a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37130a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
371447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3715c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37160a708f8fSGustavo F. Padovan 			break;
37170a708f8fSGustavo F. Padovan 
37180a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
37196327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
37202c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
37216327eb98SAndrei Emeltchenko 			else
37226327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
37236327eb98SAndrei Emeltchenko 
37242c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
37250a708f8fSGustavo F. Padovan 
3726c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
37272d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
37282d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3729c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3730c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
37310a708f8fSGustavo F. Padovan 
373236c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
37330a708f8fSGustavo F. Padovan 
3734c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37350a708f8fSGustavo F. Padovan 
37360a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3737e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
37380a708f8fSGustavo F. Padovan 
373942dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
374042dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
374142dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
374242dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
374342dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
374442dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
374542dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
374642dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
374742dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
374842dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
374942dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
37502d792818SGustavo Padovan 						   sizeof(efs),
3751e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
375242dceae2SAndrei Emeltchenko 			}
37530a708f8fSGustavo F. Padovan 			break;
37540a708f8fSGustavo F. Padovan 
37550a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3756c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
37572d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
37582d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3759c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3760c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
37610a708f8fSGustavo F. Padovan 
3762c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37630a708f8fSGustavo F. Padovan 
37642d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3765e860d2c9SBen Seri 					   (unsigned long) &rfc, endptr - ptr);
37660a708f8fSGustavo F. Padovan 
37670a708f8fSGustavo F. Padovan 			break;
37680a708f8fSGustavo F. Padovan 
37690a708f8fSGustavo F. Padovan 		default:
37700a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
37710a708f8fSGustavo F. Padovan 
37720a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
37730c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
37740a708f8fSGustavo F. Padovan 		}
37750a708f8fSGustavo F. Padovan 
37760a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3777c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37780a708f8fSGustavo F. Padovan 	}
3779fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37800a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
3781dcf4adbfSJoe Perches 	rsp->flags  = cpu_to_le16(0);
37820a708f8fSGustavo F. Padovan 
37830a708f8fSGustavo F. Padovan 	return ptr - data;
37840a708f8fSGustavo F. Padovan }
37850a708f8fSGustavo F. Padovan 
37862d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3787e860d2c9SBen Seri 				void *data, size_t size, u16 *result)
37880a708f8fSGustavo F. Padovan {
37890a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
37900a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3791e860d2c9SBen Seri 	void *endptr = data + size;
37920a708f8fSGustavo F. Padovan 	int type, olen;
37930a708f8fSGustavo F. Padovan 	unsigned long val;
379436e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
379566af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
37960a708f8fSGustavo F. Padovan 
3797fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
37980a708f8fSGustavo F. Padovan 
37990a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
38000a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
38017c9cbd0bSMarcel Holtmann 		if (len < 0)
38027c9cbd0bSMarcel Holtmann 			break;
38030a708f8fSGustavo F. Padovan 
38040a708f8fSGustavo F. Padovan 		switch (type) {
38050a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3806af3d5d1cSMarcel Holtmann 			if (olen != 2)
3807af3d5d1cSMarcel Holtmann 				break;
38080a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
38090a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
38100c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
38110a708f8fSGustavo F. Padovan 			} else
38120c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
3813af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3814af3d5d1cSMarcel Holtmann 					   endptr - ptr);
38150a708f8fSGustavo F. Padovan 			break;
38160a708f8fSGustavo F. Padovan 
38170a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3818af3d5d1cSMarcel Holtmann 			if (olen != 2)
3819af3d5d1cSMarcel Holtmann 				break;
38200c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
3821af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3822af3d5d1cSMarcel Holtmann 					   chan->flush_to, endptr - ptr);
38230a708f8fSGustavo F. Padovan 			break;
38240a708f8fSGustavo F. Padovan 
38250a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3826af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3827af3d5d1cSMarcel Holtmann 				break;
38280a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3829c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
38300c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
38310a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
383247d1ec61SGustavo F. Padovan 			chan->fcs = 0;
3833af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3834af3d5d1cSMarcel Holtmann 					   (unsigned long) &rfc, endptr - ptr);
38350a708f8fSGustavo F. Padovan 			break;
38366327eb98SAndrei Emeltchenko 
38376327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3838af3d5d1cSMarcel Holtmann 			if (olen != 2)
3839af3d5d1cSMarcel Holtmann 				break;
3840c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
38413e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3842e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
38436327eb98SAndrei Emeltchenko 			break;
384466af7aafSAndrei Emeltchenko 
384566af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3846af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3847af3d5d1cSMarcel Holtmann 				break;
384866af7aafSAndrei Emeltchenko 			memcpy(&efs, (void *)val, olen);
384966af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
385066af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
385166af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
385266af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
38532d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3854e860d2c9SBen Seri 					   (unsigned long) &efs, endptr - ptr);
385566af7aafSAndrei Emeltchenko 			break;
3856cbabee78SAndrei Emeltchenko 
3857cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3858af3d5d1cSMarcel Holtmann 			if (olen != 1)
3859af3d5d1cSMarcel Holtmann 				break;
3860cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3861cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3862f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3863cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3864cbabee78SAndrei Emeltchenko 			break;
38650a708f8fSGustavo F. Padovan 		}
38660a708f8fSGustavo F. Padovan 	}
38670a708f8fSGustavo F. Padovan 
38680c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
38690a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
38700a708f8fSGustavo F. Padovan 
38710c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
38720a708f8fSGustavo F. Padovan 
38730e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
38740a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
38750a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
387647d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
387747d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
387847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3879c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3880c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3881c20f8e35SMat Martineau 						      rfc.txwin_size);
388266af7aafSAndrei Emeltchenko 
388366af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
388466af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
388566af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
388666af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
388766af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
388866af7aafSAndrei Emeltchenko 				chan->local_flush_to =
388966af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
389066af7aafSAndrei Emeltchenko 			}
38910a708f8fSGustavo F. Padovan 			break;
389266af7aafSAndrei Emeltchenko 
38930a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
389447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38950a708f8fSGustavo F. Padovan 		}
38960a708f8fSGustavo F. Padovan 	}
38970a708f8fSGustavo F. Padovan 
3898fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
3899dcf4adbfSJoe Perches 	req->flags  = cpu_to_le16(0);
39000a708f8fSGustavo F. Padovan 
39010a708f8fSGustavo F. Padovan 	return ptr - data;
39020a708f8fSGustavo F. Padovan }
39030a708f8fSGustavo F. Padovan 
39042d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
39052d792818SGustavo Padovan 				u16 result, u16 flags)
39060a708f8fSGustavo F. Padovan {
39070a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
39080a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
39090a708f8fSGustavo F. Padovan 
3910fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
39110a708f8fSGustavo F. Padovan 
3912fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
39130a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
39140a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
39150a708f8fSGustavo F. Padovan 
39160a708f8fSGustavo F. Padovan 	return ptr - data;
39170a708f8fSGustavo F. Padovan }
39180a708f8fSGustavo F. Padovan 
391927e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
392027e2d4c8SJohan Hedberg {
392127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
392227e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
392327e2d4c8SJohan Hedberg 
392427e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
392527e2d4c8SJohan Hedberg 
392627e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
392727e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
39283916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
39290cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
3930571f7390SMallikarjun Phulari 	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
393127e2d4c8SJohan Hedberg 
393227e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
393327e2d4c8SJohan Hedberg 		       &rsp);
393427e2d4c8SJohan Hedberg }
393527e2d4c8SJohan Hedberg 
393615f02b91SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
393715f02b91SLuiz Augusto von Dentz {
393815f02b91SLuiz Augusto von Dentz 	struct {
393915f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
394015f02b91SLuiz Augusto von Dentz 		__le16 dcid[5];
394115f02b91SLuiz Augusto von Dentz 	} __packed pdu;
394215f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
394315f02b91SLuiz Augusto von Dentz 	u16 ident = chan->ident;
394415f02b91SLuiz Augusto von Dentz 	int i = 0;
394515f02b91SLuiz Augusto von Dentz 
394615f02b91SLuiz Augusto von Dentz 	if (!ident)
394715f02b91SLuiz Augusto von Dentz 		return;
394815f02b91SLuiz Augusto von Dentz 
394915f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p ident %d", chan, ident);
395015f02b91SLuiz Augusto von Dentz 
395115f02b91SLuiz Augusto von Dentz 	pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
395215f02b91SLuiz Augusto von Dentz 	pdu.rsp.mps     = cpu_to_le16(chan->mps);
395315f02b91SLuiz Augusto von Dentz 	pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
395415f02b91SLuiz Augusto von Dentz 	pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
395515f02b91SLuiz Augusto von Dentz 
395615f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
395715f02b91SLuiz Augusto von Dentz 
395815f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
395915f02b91SLuiz Augusto von Dentz 		if (chan->ident != ident)
396015f02b91SLuiz Augusto von Dentz 			continue;
396115f02b91SLuiz Augusto von Dentz 
396215f02b91SLuiz Augusto von Dentz 		/* Reset ident so only one response is sent */
396315f02b91SLuiz Augusto von Dentz 		chan->ident = 0;
396415f02b91SLuiz Augusto von Dentz 
396515f02b91SLuiz Augusto von Dentz 		/* Include all channels pending with the same ident */
396615f02b91SLuiz Augusto von Dentz 		pdu.dcid[i++] = cpu_to_le16(chan->scid);
396715f02b91SLuiz Augusto von Dentz 	}
396815f02b91SLuiz Augusto von Dentz 
396915f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
397015f02b91SLuiz Augusto von Dentz 
397115f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
397215f02b91SLuiz Augusto von Dentz 			sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
397315f02b91SLuiz Augusto von Dentz }
397415f02b91SLuiz Augusto von Dentz 
39758c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3976710f9b0aSGustavo F. Padovan {
3977710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
39788c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3979710f9b0aSGustavo F. Padovan 	u8 buf[128];
3980439f34acSAndrei Emeltchenko 	u8 rsp_code;
3981710f9b0aSGustavo F. Padovan 
3982fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3983fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3984dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3985dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3986439f34acSAndrei Emeltchenko 
3987439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3988439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3989439f34acSAndrei Emeltchenko 	else
3990439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3991439f34acSAndrei Emeltchenko 
3992439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3993439f34acSAndrei Emeltchenko 
3994439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3995710f9b0aSGustavo F. Padovan 
3996c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3997710f9b0aSGustavo F. Padovan 		return;
3998710f9b0aSGustavo F. Padovan 
3999710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4000e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
4001710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
4002710f9b0aSGustavo F. Padovan }
4003710f9b0aSGustavo F. Padovan 
400447d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
40050a708f8fSGustavo F. Padovan {
40060a708f8fSGustavo F. Padovan 	int type, olen;
40070a708f8fSGustavo F. Padovan 	unsigned long val;
4008c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
4009c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
4010c20f8e35SMat Martineau 	 */
4011c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
4012c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
4013c20f8e35SMat Martineau 		.mode = chan->mode,
4014dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
4015dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
4016c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
4017c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
4018c20f8e35SMat Martineau 	};
40190a708f8fSGustavo F. Padovan 
402047d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
40210a708f8fSGustavo F. Padovan 
40220c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
40230a708f8fSGustavo F. Padovan 		return;
40240a708f8fSGustavo F. Padovan 
40250a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
40260a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
40277c9cbd0bSMarcel Holtmann 		if (len < 0)
40287c9cbd0bSMarcel Holtmann 			break;
40290a708f8fSGustavo F. Padovan 
4030c20f8e35SMat Martineau 		switch (type) {
4031c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
4032af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
4033af3d5d1cSMarcel Holtmann 				break;
40340a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
4035c20f8e35SMat Martineau 			break;
4036c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
4037af3d5d1cSMarcel Holtmann 			if (olen != 2)
4038af3d5d1cSMarcel Holtmann 				break;
4039c20f8e35SMat Martineau 			txwin_ext = val;
4040c20f8e35SMat Martineau 			break;
4041c20f8e35SMat Martineau 		}
40420a708f8fSGustavo F. Padovan 	}
40430a708f8fSGustavo F. Padovan 
40440a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
40450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
404647d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
404747d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
404847d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
4049c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4050c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
4051c20f8e35SMat Martineau 		else
4052c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
4053c20f8e35SMat Martineau 					      rfc.txwin_size);
40540a708f8fSGustavo F. Padovan 		break;
40550a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
405647d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
40570a708f8fSGustavo F. Padovan 	}
40580a708f8fSGustavo F. Padovan }
40590a708f8fSGustavo F. Padovan 
40602d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
4061cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4062cb3b3152SJohan Hedberg 				    u8 *data)
40630a708f8fSGustavo F. Padovan {
4064e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
40650a708f8fSGustavo F. Padovan 
4066cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
4067cb3b3152SJohan Hedberg 		return -EPROTO;
4068cb3b3152SJohan Hedberg 
4069e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
40700a708f8fSGustavo F. Padovan 		return 0;
40710a708f8fSGustavo F. Padovan 
40720a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
40730a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
407417cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
40750a708f8fSGustavo F. Padovan 
40760a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
40770a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
40780a708f8fSGustavo F. Padovan 
40790a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
40800a708f8fSGustavo F. Padovan 	}
40810a708f8fSGustavo F. Padovan 
40820a708f8fSGustavo F. Padovan 	return 0;
40830a708f8fSGustavo F. Padovan }
40840a708f8fSGustavo F. Padovan 
40851700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
40861700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
40874c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
40880a708f8fSGustavo F. Padovan {
40890a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
40900a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
409123691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
40920a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
40930a708f8fSGustavo F. Padovan 
40940a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
40950a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
40960a708f8fSGustavo F. Padovan 
4097097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
40980a708f8fSGustavo F. Padovan 
40990a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
41006f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
4101bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
410223691d75SGustavo F. Padovan 	if (!pchan) {
41030a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
41040a708f8fSGustavo F. Padovan 		goto sendresp;
41050a708f8fSGustavo F. Padovan 	}
41060a708f8fSGustavo F. Padovan 
41073df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41088ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
41090a708f8fSGustavo F. Padovan 
41100a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
4111dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
41120a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
41139f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
41140a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
41150a708f8fSGustavo F. Padovan 		goto response;
41160a708f8fSGustavo F. Padovan 	}
41170a708f8fSGustavo F. Padovan 
41180a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
41190a708f8fSGustavo F. Padovan 
4120dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
4121dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
4122dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
41232dfa1003SGustavo Padovan 		goto response;
4124dd1a8f8aSMallikarjun Phulari 	}
4125dd1a8f8aSMallikarjun Phulari 
4126dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
4127dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
4128dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
4129dd1a8f8aSMallikarjun Phulari 		goto response;
4130dd1a8f8aSMallikarjun Phulari 	}
41312dfa1003SGustavo Padovan 
413280b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
413380808e43SGustavo F. Padovan 	if (!chan)
41340a708f8fSGustavo F. Padovan 		goto response;
41350a708f8fSGustavo F. Padovan 
4136330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
4137330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
4138330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
4139330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
4140330b6c15SSyam Sidhardhan 	 */
4141330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
4142330b6c15SSyam Sidhardhan 
41437eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
41447eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
4145a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
4146a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
4147fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
4148fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
41491700915fSMat Martineau 	chan->local_amp_id = amp_id;
41500a708f8fSGustavo F. Padovan 
41516be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
415248454079SGustavo F. Padovan 
4153fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
41540a708f8fSGustavo F. Padovan 
41558d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
41560a708f8fSGustavo F. Padovan 
4157fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
41580a708f8fSGustavo F. Padovan 
41590a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4160e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
4161bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4162f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
41630a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
41640a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
41652dc4e510SGustavo Padovan 				chan->ops->defer(chan);
41660a708f8fSGustavo F. Padovan 			} else {
41671700915fSMat Martineau 				/* Force pending result for AMP controllers.
41681700915fSMat Martineau 				 * The connection will succeed after the
41691700915fSMat Martineau 				 * physical link is up.
41701700915fSMat Martineau 				 */
41716ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4172f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
41730a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
41746ed971caSMarcel Holtmann 				} else {
4175f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
41766ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
41771700915fSMat Martineau 				}
41780a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
41790a708f8fSGustavo F. Padovan 			}
41800a708f8fSGustavo F. Padovan 		} else {
4181f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
41820a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
41830a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
41840a708f8fSGustavo F. Padovan 		}
41850a708f8fSGustavo F. Padovan 	} else {
4186f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
41870a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
41880a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
41890a708f8fSGustavo F. Padovan 	}
41900a708f8fSGustavo F. Padovan 
41910a708f8fSGustavo F. Padovan response:
41928ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
41933df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4194a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
41950a708f8fSGustavo F. Padovan 
41960a708f8fSGustavo F. Padovan sendresp:
41970a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
41980a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
41990a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
42000a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
42014c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
42020a708f8fSGustavo F. Padovan 
42030a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
42040a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4205dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
42060a708f8fSGustavo F. Padovan 
42070a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
42080a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
42090a708f8fSGustavo F. Padovan 
4210ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
42110a708f8fSGustavo F. Padovan 
42122d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
42132d792818SGustavo Padovan 			       sizeof(info), &info);
42140a708f8fSGustavo F. Padovan 	}
42150a708f8fSGustavo F. Padovan 
4216c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
42170a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
42180a708f8fSGustavo F. Padovan 		u8 buf[128];
4219c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
42200a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4221e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
422273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
42230a708f8fSGustavo F. Padovan 	}
42241700915fSMat Martineau 
42251700915fSMat Martineau 	return chan;
42264c89b6aaSMat Martineau }
42270a708f8fSGustavo F. Padovan 
42284c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4229cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
42304c89b6aaSMat Martineau {
42317b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
42327b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
42337b064edaSJaganath Kanakkassery 
4234cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4235cb3b3152SJohan Hedberg 		return -EPROTO;
4236cb3b3152SJohan Hedberg 
42377b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
4238d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
42397b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
424048ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, hcon, 0, NULL, 0);
42417b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
42427b064edaSJaganath Kanakkassery 
4243300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
42440a708f8fSGustavo F. Padovan 	return 0;
42450a708f8fSGustavo F. Padovan }
42460a708f8fSGustavo F. Padovan 
42475909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4248cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4249cb3b3152SJohan Hedberg 				    u8 *data)
42500a708f8fSGustavo F. Padovan {
42510a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
42520a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
425348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42540a708f8fSGustavo F. Padovan 	u8 req[128];
42553df91ea2SAndrei Emeltchenko 	int err;
42560a708f8fSGustavo F. Padovan 
4257cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4258cb3b3152SJohan Hedberg 		return -EPROTO;
4259cb3b3152SJohan Hedberg 
42600a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
42610a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
42620a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
42630a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
42640a708f8fSGustavo F. Padovan 
42651b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
42661b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
42670a708f8fSGustavo F. Padovan 
42683df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
42693df91ea2SAndrei Emeltchenko 
42700a708f8fSGustavo F. Padovan 	if (scid) {
42713df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
42723df91ea2SAndrei Emeltchenko 		if (!chan) {
427321870b52SJohan Hedberg 			err = -EBADSLT;
42743df91ea2SAndrei Emeltchenko 			goto unlock;
42753df91ea2SAndrei Emeltchenko 		}
42760a708f8fSGustavo F. Padovan 	} else {
42773df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
42783df91ea2SAndrei Emeltchenko 		if (!chan) {
427921870b52SJohan Hedberg 			err = -EBADSLT;
42803df91ea2SAndrei Emeltchenko 			goto unlock;
42813df91ea2SAndrei Emeltchenko 		}
42820a708f8fSGustavo F. Padovan 	}
42830a708f8fSGustavo F. Padovan 
42843df91ea2SAndrei Emeltchenko 	err = 0;
42853df91ea2SAndrei Emeltchenko 
42866be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
428748454079SGustavo F. Padovan 
42880a708f8fSGustavo F. Padovan 	switch (result) {
42890a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
429089bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4291fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4292fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4293c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
42940a708f8fSGustavo F. Padovan 
4295c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
42960a708f8fSGustavo F. Padovan 			break;
42970a708f8fSGustavo F. Padovan 
42980a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4299e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
430073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43010a708f8fSGustavo F. Padovan 		break;
43020a708f8fSGustavo F. Padovan 
43030a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4304c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
43050a708f8fSGustavo F. Padovan 		break;
43060a708f8fSGustavo F. Padovan 
43070a708f8fSGustavo F. Padovan 	default:
430848454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
43090a708f8fSGustavo F. Padovan 		break;
43100a708f8fSGustavo F. Padovan 	}
43110a708f8fSGustavo F. Padovan 
43126be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43133df91ea2SAndrei Emeltchenko 
43143df91ea2SAndrei Emeltchenko unlock:
43153df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43163df91ea2SAndrei Emeltchenko 
43173df91ea2SAndrei Emeltchenko 	return err;
43180a708f8fSGustavo F. Padovan }
43190a708f8fSGustavo F. Padovan 
432047d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
43210a708f8fSGustavo F. Padovan {
43220a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
43230a708f8fSGustavo F. Padovan 	 * sides request it.
43240a708f8fSGustavo F. Padovan 	 */
43250c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
432647d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4327f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
432847d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
43290a708f8fSGustavo F. Padovan }
43300a708f8fSGustavo F. Padovan 
433129d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
433229d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
433329d8a590SAndrei Emeltchenko {
433429d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
433529d8a590SAndrei Emeltchenko 
433629d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
433729d8a590SAndrei Emeltchenko 	       flags);
433829d8a590SAndrei Emeltchenko 
433929d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
434029d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
434129d8a590SAndrei Emeltchenko 
434229d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
434329d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
434429d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
434529d8a590SAndrei Emeltchenko }
434629d8a590SAndrei Emeltchenko 
4347662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4348662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4349662d652dSJohan Hedberg {
4350662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4351662d652dSJohan Hedberg 
4352dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4353662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4354662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4355662d652dSJohan Hedberg 
4356662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4357662d652dSJohan Hedberg }
4358662d652dSJohan Hedberg 
43592d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
43602d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
43612d792818SGustavo Padovan 				   u8 *data)
43620a708f8fSGustavo F. Padovan {
43630a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
43640a708f8fSGustavo F. Padovan 	u16 dcid, flags;
43650a708f8fSGustavo F. Padovan 	u8 rsp[64];
436648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43673c588192SMat Martineau 	int len, err = 0;
43680a708f8fSGustavo F. Padovan 
4369cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4370cb3b3152SJohan Hedberg 		return -EPROTO;
4371cb3b3152SJohan Hedberg 
43720a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
43730a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
43740a708f8fSGustavo F. Padovan 
43750a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
43760a708f8fSGustavo F. Padovan 
4377baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4378662d652dSJohan Hedberg 	if (!chan) {
4379662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4380662d652dSJohan Hedberg 		return 0;
4381662d652dSJohan Hedberg 	}
43820a708f8fSGustavo F. Padovan 
438396298f64SHoward Chung 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
438496298f64SHoward Chung 	    chan->state != BT_CONNECTED) {
4385662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4386662d652dSJohan Hedberg 				       chan->dcid);
43870a708f8fSGustavo F. Padovan 		goto unlock;
43880a708f8fSGustavo F. Padovan 	}
43890a708f8fSGustavo F. Padovan 
43900a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
43910a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4392cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
43930a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4394fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
43950a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
43960a708f8fSGustavo F. Padovan 		goto unlock;
43970a708f8fSGustavo F. Padovan 	}
43980a708f8fSGustavo F. Padovan 
43990a708f8fSGustavo F. Padovan 	/* Store config. */
440073ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
440173ffa904SGustavo F. Padovan 	chan->conf_len += len;
44020a708f8fSGustavo F. Padovan 
440359e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
44040a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
44050a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4406fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
44075325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
44080a708f8fSGustavo F. Padovan 		goto unlock;
44090a708f8fSGustavo F. Padovan 	}
44100a708f8fSGustavo F. Padovan 
44110a708f8fSGustavo F. Padovan 	/* Complete config. */
4412e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
44130a708f8fSGustavo F. Padovan 	if (len < 0) {
44145e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
44150a708f8fSGustavo F. Padovan 		goto unlock;
44160a708f8fSGustavo F. Padovan 	}
44170a708f8fSGustavo F. Padovan 
44181500109bSMat Martineau 	chan->ident = cmd->ident;
44190a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
442073ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
44210a708f8fSGustavo F. Padovan 
44220a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
442373ffa904SGustavo F. Padovan 	chan->conf_len = 0;
44240a708f8fSGustavo F. Padovan 
4425c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
44260a708f8fSGustavo F. Padovan 		goto unlock;
44270a708f8fSGustavo F. Padovan 
4428c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
442947d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44300a708f8fSGustavo F. Padovan 
4431105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4432105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44333c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44340a708f8fSGustavo F. Padovan 
44353c588192SMat Martineau 		if (err < 0)
44365e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44373c588192SMat Martineau 		else
4438cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44393c588192SMat Martineau 
44400a708f8fSGustavo F. Padovan 		goto unlock;
44410a708f8fSGustavo F. Padovan 	}
44420a708f8fSGustavo F. Padovan 
4443c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
44440a708f8fSGustavo F. Padovan 		u8 buf[64];
44450a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4446e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
444773ffa904SGustavo F. Padovan 		chan->num_conf_req++;
44480a708f8fSGustavo F. Padovan 	}
44490a708f8fSGustavo F. Padovan 
445049c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
44510e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
44520e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
44530e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
44540e8b207eSAndrei Emeltchenko 
44550e8b207eSAndrei Emeltchenko 		/* check compatibility */
44560e8b207eSAndrei Emeltchenko 
445779de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4458f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
445929d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
446079de886dSAndrei Emeltchenko 		else
446179de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
44620e8b207eSAndrei Emeltchenko 	}
44630e8b207eSAndrei Emeltchenko 
44640a708f8fSGustavo F. Padovan unlock:
44656be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44663c588192SMat Martineau 	return err;
44670a708f8fSGustavo F. Padovan }
44680a708f8fSGustavo F. Padovan 
44692d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4470cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4471cb3b3152SJohan Hedberg 				   u8 *data)
44720a708f8fSGustavo F. Padovan {
44730a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
44740a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
447548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4476cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
44773c588192SMat Martineau 	int err = 0;
44780a708f8fSGustavo F. Padovan 
4479cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4480cb3b3152SJohan Hedberg 		return -EPROTO;
4481cb3b3152SJohan Hedberg 
44820a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
44830a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
44840a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
44850a708f8fSGustavo F. Padovan 
448661386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
448761386cbaSAndrei Emeltchenko 	       result, len);
44880a708f8fSGustavo F. Padovan 
4489baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
449048454079SGustavo F. Padovan 	if (!chan)
44910a708f8fSGustavo F. Padovan 		return 0;
44920a708f8fSGustavo F. Padovan 
44930a708f8fSGustavo F. Padovan 	switch (result) {
44940a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
449547d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
44960e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
44970a708f8fSGustavo F. Padovan 		break;
44980a708f8fSGustavo F. Padovan 
44990e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
45000e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
45010e8b207eSAndrei Emeltchenko 
45020e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
45030e8b207eSAndrei Emeltchenko 			char buf[64];
45040e8b207eSAndrei Emeltchenko 
45050e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4506e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
45070e8b207eSAndrei Emeltchenko 			if (len < 0) {
45085e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45090e8b207eSAndrei Emeltchenko 				goto done;
45100e8b207eSAndrei Emeltchenko 			}
45110e8b207eSAndrei Emeltchenko 
4512f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
451379de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
451479de886dSAndrei Emeltchenko 							0);
45155ce66b59SAndrei Emeltchenko 			} else {
45165ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
45175ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
451879de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
45190e8b207eSAndrei Emeltchenko 				}
45205ce66b59SAndrei Emeltchenko 			}
45215ce66b59SAndrei Emeltchenko 		}
45220e8b207eSAndrei Emeltchenko 		goto done;
45230e8b207eSAndrei Emeltchenko 
452498d2c3e1SBastien Nocera 	case L2CAP_CONF_UNKNOWN:
45250a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
452673ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
45270a708f8fSGustavo F. Padovan 			char req[64];
45280a708f8fSGustavo F. Padovan 
45290a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
45305e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45310a708f8fSGustavo F. Padovan 				goto done;
45320a708f8fSGustavo F. Padovan 			}
45330a708f8fSGustavo F. Padovan 
45340a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
45350a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4536b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4537e860d2c9SBen Seri 						   req, sizeof(req), &result);
45380a708f8fSGustavo F. Padovan 			if (len < 0) {
45395e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45400a708f8fSGustavo F. Padovan 				goto done;
45410a708f8fSGustavo F. Padovan 			}
45420a708f8fSGustavo F. Padovan 
45430a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
45440a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
454573ffa904SGustavo F. Padovan 			chan->num_conf_req++;
45460a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
45470a708f8fSGustavo F. Padovan 				goto done;
45480a708f8fSGustavo F. Padovan 			break;
45490a708f8fSGustavo F. Padovan 		}
455019186c7bSGustavo A. R. Silva 		fallthrough;
45510a708f8fSGustavo F. Padovan 
45520a708f8fSGustavo F. Padovan 	default:
45536be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
45542e0052e4SAndrei Emeltchenko 
4555ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
45565e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
45570a708f8fSGustavo F. Padovan 		goto done;
45580a708f8fSGustavo F. Padovan 	}
45590a708f8fSGustavo F. Padovan 
456059e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
45610a708f8fSGustavo F. Padovan 		goto done;
45620a708f8fSGustavo F. Padovan 
4563c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
45640a708f8fSGustavo F. Padovan 
4565c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
456647d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
45670a708f8fSGustavo F. Padovan 
4568105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4569105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
45703c588192SMat Martineau 			err = l2cap_ertm_init(chan);
45710a708f8fSGustavo F. Padovan 
45723c588192SMat Martineau 		if (err < 0)
45735e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
45743c588192SMat Martineau 		else
4575cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
45760a708f8fSGustavo F. Padovan 	}
45770a708f8fSGustavo F. Padovan 
45780a708f8fSGustavo F. Padovan done:
45796be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45803c588192SMat Martineau 	return err;
45810a708f8fSGustavo F. Padovan }
45820a708f8fSGustavo F. Padovan 
45832d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4584cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4585cb3b3152SJohan Hedberg 				       u8 *data)
45860a708f8fSGustavo F. Padovan {
45870a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
45880a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
45890a708f8fSGustavo F. Padovan 	u16 dcid, scid;
459048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
45910a708f8fSGustavo F. Padovan 
4592cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4593cb3b3152SJohan Hedberg 		return -EPROTO;
4594cb3b3152SJohan Hedberg 
45950a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
45960a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
45970a708f8fSGustavo F. Padovan 
45980a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
45990a708f8fSGustavo F. Padovan 
46003df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
46013df91ea2SAndrei Emeltchenko 
46023df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
46033df91ea2SAndrei Emeltchenko 	if (!chan) {
46043df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4605662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4606662d652dSJohan Hedberg 		return 0;
46073df91ea2SAndrei Emeltchenko 	}
46080a708f8fSGustavo F. Padovan 
46096c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
46106be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
46116be36555SAndrei Emeltchenko 
4612fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4613fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
46140a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
46150a708f8fSGustavo F. Padovan 
46165ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
46170a708f8fSGustavo F. Padovan 
461848454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
46196be36555SAndrei Emeltchenko 
462080b98027SGustavo Padovan 	chan->ops->close(chan);
46216c08fc89SManish Mandlik 
46226c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
462361d6ef3eSMat Martineau 	l2cap_chan_put(chan);
46243df91ea2SAndrei Emeltchenko 
46253df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46263df91ea2SAndrei Emeltchenko 
46270a708f8fSGustavo F. Padovan 	return 0;
46280a708f8fSGustavo F. Padovan }
46290a708f8fSGustavo F. Padovan 
46302d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4631cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4632cb3b3152SJohan Hedberg 				       u8 *data)
46330a708f8fSGustavo F. Padovan {
46340a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
46350a708f8fSGustavo F. Padovan 	u16 dcid, scid;
463648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
46370a708f8fSGustavo F. Padovan 
4638cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4639cb3b3152SJohan Hedberg 		return -EPROTO;
4640cb3b3152SJohan Hedberg 
46410a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
46420a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
46430a708f8fSGustavo F. Padovan 
46440a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
46450a708f8fSGustavo F. Padovan 
46463df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
46473df91ea2SAndrei Emeltchenko 
46483df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
46493df91ea2SAndrei Emeltchenko 	if (!chan) {
46503df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
46510a708f8fSGustavo F. Padovan 		return 0;
46523df91ea2SAndrei Emeltchenko 	}
46530a708f8fSGustavo F. Padovan 
46546c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
46556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
465648454079SGustavo F. Padovan 
465728261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
465828261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
46596c08fc89SManish Mandlik 		l2cap_chan_put(chan);
466028261da8SMatias Karhumaa 		mutex_unlock(&conn->chan_lock);
466128261da8SMatias Karhumaa 		return 0;
466228261da8SMatias Karhumaa 	}
466328261da8SMatias Karhumaa 
466448454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
46656be36555SAndrei Emeltchenko 
466680b98027SGustavo Padovan 	chan->ops->close(chan);
46676c08fc89SManish Mandlik 
46686c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
466961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
46703df91ea2SAndrei Emeltchenko 
46713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46723df91ea2SAndrei Emeltchenko 
46730a708f8fSGustavo F. Padovan 	return 0;
46740a708f8fSGustavo F. Padovan }
46750a708f8fSGustavo F. Padovan 
46762d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4677cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4678cb3b3152SJohan Hedberg 					u8 *data)
46790a708f8fSGustavo F. Padovan {
46800a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
46810a708f8fSGustavo F. Padovan 	u16 type;
46820a708f8fSGustavo F. Padovan 
4683cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4684cb3b3152SJohan Hedberg 		return -EPROTO;
4685cb3b3152SJohan Hedberg 
46860a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
46870a708f8fSGustavo F. Padovan 
46880a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
46890a708f8fSGustavo F. Padovan 
46900a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
46910a708f8fSGustavo F. Padovan 		u8 buf[8];
46920a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
46930a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4694dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4695dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
46960a708f8fSGustavo F. Padovan 		if (!disable_ertm)
46970a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
46980a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
46990bd49fc7SJohan Hedberg 		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
47006327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
47016327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4702a5fd6f30SAndrei Emeltchenko 
47030a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
47042d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47052d792818SGustavo Padovan 			       buf);
47060a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
47070a708f8fSGustavo F. Padovan 		u8 buf[12];
47080a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
470950a147cdSMat Martineau 
4710dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4711dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
47120bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
47130bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
47142d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47152d792818SGustavo Padovan 			       buf);
47160a708f8fSGustavo F. Padovan 	} else {
47170a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
47180a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4719dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
47202d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
47212d792818SGustavo Padovan 			       &rsp);
47220a708f8fSGustavo F. Padovan 	}
47230a708f8fSGustavo F. Padovan 
47240a708f8fSGustavo F. Padovan 	return 0;
47250a708f8fSGustavo F. Padovan }
47260a708f8fSGustavo F. Padovan 
47272d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4728cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4729cb3b3152SJohan Hedberg 					u8 *data)
47300a708f8fSGustavo F. Padovan {
47310a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
47320a708f8fSGustavo F. Padovan 	u16 type, result;
47330a708f8fSGustavo F. Padovan 
47343f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4735cb3b3152SJohan Hedberg 		return -EPROTO;
4736cb3b3152SJohan Hedberg 
47370a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
47380a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
47390a708f8fSGustavo F. Padovan 
47400a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
47410a708f8fSGustavo F. Padovan 
4742e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4743e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4744e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4745e90165beSAndrei Emeltchenko 		return 0;
4746e90165beSAndrei Emeltchenko 
474717cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
47480a708f8fSGustavo F. Padovan 
47490a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
47500a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47510a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
47520a708f8fSGustavo F. Padovan 
47530a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
47540a708f8fSGustavo F. Padovan 
47550a708f8fSGustavo F. Padovan 		return 0;
47560a708f8fSGustavo F. Padovan 	}
47570a708f8fSGustavo F. Padovan 
4758978c93b9SAndrei Emeltchenko 	switch (type) {
4759978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
47600a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
47610a708f8fSGustavo F. Padovan 
47620a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
47630a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4764dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
47650a708f8fSGustavo F. Padovan 
47660a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
47670a708f8fSGustavo F. Padovan 
47680a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
47690a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
47700a708f8fSGustavo F. Padovan 		} else {
47710a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47720a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
47730a708f8fSGustavo F. Padovan 
47740a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
47750a708f8fSGustavo F. Padovan 		}
4776978c93b9SAndrei Emeltchenko 		break;
4777978c93b9SAndrei Emeltchenko 
4778978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
47790bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
47800a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47810a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
47820a708f8fSGustavo F. Padovan 
47830a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4784978c93b9SAndrei Emeltchenko 		break;
47850a708f8fSGustavo F. Padovan 	}
47860a708f8fSGustavo F. Padovan 
47870a708f8fSGustavo F. Padovan 	return 0;
47880a708f8fSGustavo F. Padovan }
47890a708f8fSGustavo F. Padovan 
47901700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
47912d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
47922d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4793f94ff6ffSMat Martineau {
4794f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
47956e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
47961700915fSMat Martineau 	struct l2cap_chan *chan;
47976e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4798f94ff6ffSMat Martineau 	u16 psm, scid;
4799f94ff6ffSMat Martineau 
4800f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4801f94ff6ffSMat Martineau 		return -EPROTO;
4802f94ff6ffSMat Martineau 
48030bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4804f94ff6ffSMat Martineau 		return -EINVAL;
4805f94ff6ffSMat Martineau 
4806f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4807f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4808f94ff6ffSMat Martineau 
4809ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4810f94ff6ffSMat Martineau 
48116e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
48126ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
48136e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48146e1df6a6SAndrei Emeltchenko 			      req->amp_id);
48156e1df6a6SAndrei Emeltchenko 		return 0;
48166e1df6a6SAndrei Emeltchenko 	}
48171700915fSMat Martineau 
48181700915fSMat Martineau 	/* Validate AMP controller id */
48191700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
48206e1df6a6SAndrei Emeltchenko 	if (!hdev)
48216e1df6a6SAndrei Emeltchenko 		goto error;
48221700915fSMat Martineau 
48236e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
48246e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
48256e1df6a6SAndrei Emeltchenko 		goto error;
48266e1df6a6SAndrei Emeltchenko 	}
48276e1df6a6SAndrei Emeltchenko 
48286e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48296e1df6a6SAndrei Emeltchenko 			     req->amp_id);
48306e1df6a6SAndrei Emeltchenko 	if (chan) {
48316e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
48326e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
48336e1df6a6SAndrei Emeltchenko 
483498e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
483598e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
48366e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
48376e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4838662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4839662d652dSJohan Hedberg 					       chan->dcid);
4840662d652dSJohan Hedberg 			return 0;
48416e1df6a6SAndrei Emeltchenko 		}
48426e1df6a6SAndrei Emeltchenko 
48436e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
48446e1df6a6SAndrei Emeltchenko 
48456e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
48466e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4847fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
48486e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
48496e1df6a6SAndrei Emeltchenko 	}
48506e1df6a6SAndrei Emeltchenko 
48516e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
48526e1df6a6SAndrei Emeltchenko 
48536e1df6a6SAndrei Emeltchenko 	return 0;
48546e1df6a6SAndrei Emeltchenko 
48556e1df6a6SAndrei Emeltchenko error:
4856f94ff6ffSMat Martineau 	rsp.dcid = 0;
4857f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
4858dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
4859dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4860f94ff6ffSMat Martineau 
4861f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4862f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4863f94ff6ffSMat Martineau 
4864dc280801SJohan Hedberg 	return 0;
4865f94ff6ffSMat Martineau }
4866f94ff6ffSMat Martineau 
48678eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
48688eb200bdSMat Martineau {
48698eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
48708eb200bdSMat Martineau 	u8 ident;
48718eb200bdSMat Martineau 
48728eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
48738eb200bdSMat Martineau 
48748eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
48758eb200bdSMat Martineau 	chan->ident = ident;
48768eb200bdSMat Martineau 
48778eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
48788eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
48798eb200bdSMat Martineau 
48808eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
48818eb200bdSMat Martineau 		       &req);
48828eb200bdSMat Martineau 
48838eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
48848eb200bdSMat Martineau }
48858eb200bdSMat Martineau 
48861500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
48878d5a04a1SMat Martineau {
48888d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
48898d5a04a1SMat Martineau 
48901500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
48918d5a04a1SMat Martineau 
48921500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
48938d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
48948d5a04a1SMat Martineau 
48951500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
48961500109bSMat Martineau 		       sizeof(rsp), &rsp);
48978d5a04a1SMat Martineau }
48988d5a04a1SMat Martineau 
48995b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
49008d5a04a1SMat Martineau {
49018d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49028d5a04a1SMat Martineau 
49035b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
49048d5a04a1SMat Martineau 
49055b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
49068d5a04a1SMat Martineau 
49075b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
49088d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
49098d5a04a1SMat Martineau 
49105b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
49115b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49125b155ef9SMat Martineau 
49135b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
49145b155ef9SMat Martineau }
49155b155ef9SMat Martineau 
49165b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
49175b155ef9SMat Martineau {
49185b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49195b155ef9SMat Martineau 
49205b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
49215b155ef9SMat Martineau 
49225b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
4923dcf4adbfSJoe Perches 	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
49245b155ef9SMat Martineau 
49255b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
49265b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49278d5a04a1SMat Martineau }
49288d5a04a1SMat Martineau 
49298d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
49308d5a04a1SMat Martineau 					 u16 icid)
49318d5a04a1SMat Martineau {
49328d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
49338d5a04a1SMat Martineau 
4934ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
49358d5a04a1SMat Martineau 
49368d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
49378d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
49388d5a04a1SMat Martineau }
49398d5a04a1SMat Martineau 
49405f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
49415f3847a4SMat Martineau {
49425f3847a4SMat Martineau 	chan->hs_hchan = NULL;
49435f3847a4SMat Martineau 	chan->hs_hcon = NULL;
49445f3847a4SMat Martineau 
49455f3847a4SMat Martineau 	/* Placeholder - release the logical link */
49465f3847a4SMat Martineau }
49475f3847a4SMat Martineau 
49481500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
49491500109bSMat Martineau {
49501500109bSMat Martineau 	/* Logical link setup failed */
49511500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
49521500109bSMat Martineau 		/* Create channel failure, disconnect */
49535e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
49541500109bSMat Martineau 		return;
49551500109bSMat Martineau 	}
49561500109bSMat Martineau 
49571500109bSMat Martineau 	switch (chan->move_role) {
49581500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
49591500109bSMat Martineau 		l2cap_move_done(chan);
49601500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
49611500109bSMat Martineau 		break;
49621500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
49631500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
49641500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
49651500109bSMat Martineau 			/* Remote has only sent pending or
49661500109bSMat Martineau 			 * success responses, clean up
49671500109bSMat Martineau 			 */
49681500109bSMat Martineau 			l2cap_move_done(chan);
49691500109bSMat Martineau 		}
49701500109bSMat Martineau 
49711500109bSMat Martineau 		/* Other amp move states imply that the move
49721500109bSMat Martineau 		 * has already aborted
49731500109bSMat Martineau 		 */
49741500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
49751500109bSMat Martineau 		break;
49761500109bSMat Martineau 	}
49771500109bSMat Martineau }
49781500109bSMat Martineau 
49791500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
49801500109bSMat Martineau 					struct hci_chan *hchan)
49811500109bSMat Martineau {
49821500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
49831500109bSMat Martineau 
4984336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
49851500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
49861500109bSMat Martineau 
498735ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
49881500109bSMat Martineau 
49891500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4990fe79c6feSAndrei Emeltchenko 		int err;
49911500109bSMat Martineau 
49921500109bSMat Martineau 		set_default_fcs(chan);
49931500109bSMat Martineau 
49941500109bSMat Martineau 		err = l2cap_ertm_init(chan);
49951500109bSMat Martineau 		if (err < 0)
49965e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
49971500109bSMat Martineau 		else
49981500109bSMat Martineau 			l2cap_chan_ready(chan);
49991500109bSMat Martineau 	}
50001500109bSMat Martineau }
50011500109bSMat Martineau 
50021500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
50031500109bSMat Martineau 				      struct hci_chan *hchan)
50041500109bSMat Martineau {
50051500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
50061500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
50071500109bSMat Martineau 
50081500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
50091500109bSMat Martineau 
50101500109bSMat Martineau 	switch (chan->move_state) {
50111500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50121500109bSMat Martineau 		/* Move confirm will be sent after a success
50131500109bSMat Martineau 		 * response is received
50141500109bSMat Martineau 		 */
50151500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50161500109bSMat Martineau 		break;
50171500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
50181500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
50191500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50201500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
50211500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50221500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50231500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50241500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
50251500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
50261500109bSMat Martineau 		}
50271500109bSMat Martineau 		break;
50281500109bSMat Martineau 	default:
50291500109bSMat Martineau 		/* Move was not in expected state, free the channel */
50301500109bSMat Martineau 		__release_logical_link(chan);
50311500109bSMat Martineau 
50321500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
50331500109bSMat Martineau 	}
50341500109bSMat Martineau }
50351500109bSMat Martineau 
50361500109bSMat Martineau /* Call with chan locked */
503727695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
50385b155ef9SMat Martineau 		       u8 status)
50395b155ef9SMat Martineau {
50401500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
50411500109bSMat Martineau 
50421500109bSMat Martineau 	if (status) {
50431500109bSMat Martineau 		l2cap_logical_fail(chan);
50441500109bSMat Martineau 		__release_logical_link(chan);
50455b155ef9SMat Martineau 		return;
50465b155ef9SMat Martineau 	}
50475b155ef9SMat Martineau 
50481500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
50491500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
50506ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
50511500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
50521500109bSMat Martineau 	} else {
50531500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
50541500109bSMat Martineau 	}
50551500109bSMat Martineau }
50561500109bSMat Martineau 
50573f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
50583f7a56c4SMat Martineau {
50593f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
50603f7a56c4SMat Martineau 
50616ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
50623f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
50633f7a56c4SMat Martineau 			return;
50643f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
50653f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
50663f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
50673f7a56c4SMat Martineau 	} else {
50683f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
50693f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50703f7a56c4SMat Martineau 		chan->move_id = 0;
50713f7a56c4SMat Martineau 		l2cap_move_setup(chan);
50723f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
50733f7a56c4SMat Martineau 	}
50743f7a56c4SMat Martineau }
50753f7a56c4SMat Martineau 
50768eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
50778eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
50788eb200bdSMat Martineau {
507962748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
508062748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
508162748ca1SAndrei Emeltchenko 
508212d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
508312d6cc60SAndrei Emeltchenko 
508462748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
508562748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
508662748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
508762748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
508862748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
508962748ca1SAndrei Emeltchenko 		} else {
509062748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
509162748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
509262748ca1SAndrei Emeltchenko 		}
509362748ca1SAndrei Emeltchenko 
509462748ca1SAndrei Emeltchenko 		return;
509562748ca1SAndrei Emeltchenko 	}
509662748ca1SAndrei Emeltchenko 
509762748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
509862748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
50998eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
51008eb200bdSMat Martineau 		char buf[128];
51018eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
51028eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
51038eb200bdSMat Martineau 
51048eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
51058eb200bdSMat Martineau 			/* Send successful response */
5106dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
5107dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51088eb200bdSMat Martineau 		} else {
51098eb200bdSMat Martineau 			/* Send negative response */
5110dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
5111dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51128eb200bdSMat Martineau 		}
51138eb200bdSMat Martineau 
51148eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
51158eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
51168eb200bdSMat Martineau 
51178eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
5118f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
51198eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
51208eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
51218eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
5122e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
51238eb200bdSMat Martineau 			chan->num_conf_req++;
51248eb200bdSMat Martineau 		}
51258eb200bdSMat Martineau 	}
51268eb200bdSMat Martineau }
51278eb200bdSMat Martineau 
51288eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
51298eb200bdSMat Martineau 				   u8 remote_amp_id)
51308eb200bdSMat Martineau {
51318eb200bdSMat Martineau 	l2cap_move_setup(chan);
51328eb200bdSMat Martineau 	chan->move_id = local_amp_id;
51338eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
51348eb200bdSMat Martineau 
51358eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
51368eb200bdSMat Martineau }
51378eb200bdSMat Martineau 
51388eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
51398eb200bdSMat Martineau {
51408eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
51418eb200bdSMat Martineau 
51428eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
51438eb200bdSMat Martineau 
51448eb200bdSMat Martineau 	if (hchan) {
51458eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
51468eb200bdSMat Martineau 			/* Logical link is ready to go */
51478eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
51488eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
51498eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
51508eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
51518eb200bdSMat Martineau 
51528eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
51538eb200bdSMat Martineau 		} else {
51548eb200bdSMat Martineau 			/* Wait for logical link to be ready */
51558eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51568eb200bdSMat Martineau 		}
51578eb200bdSMat Martineau 	} else {
51588eb200bdSMat Martineau 		/* Logical link not available */
51598eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
51608eb200bdSMat Martineau 	}
51618eb200bdSMat Martineau }
51628eb200bdSMat Martineau 
51638eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
51648eb200bdSMat Martineau {
51658eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
51668eb200bdSMat Martineau 		u8 rsp_result;
51678eb200bdSMat Martineau 		if (result == -EINVAL)
51688eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
51698eb200bdSMat Martineau 		else
51708eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
51718eb200bdSMat Martineau 
51728eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
51738eb200bdSMat Martineau 	}
51748eb200bdSMat Martineau 
51758eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
51768eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
51778eb200bdSMat Martineau 
51788eb200bdSMat Martineau 	/* Restart data transmission */
51798eb200bdSMat Martineau 	l2cap_ertm_send(chan);
51808eb200bdSMat Martineau }
51818eb200bdSMat Martineau 
5182a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5183a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
51848eb200bdSMat Martineau {
5185770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5186fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5187770bfefaSAndrei Emeltchenko 
51888eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
51898eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
51908eb200bdSMat Martineau 
5191df66499aSDan Carpenter 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED)
51928eb200bdSMat Martineau 		return;
51938eb200bdSMat Martineau 
51948eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
51958eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
51968eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
51978eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
51988eb200bdSMat Martineau 	} else {
51998eb200bdSMat Martineau 		switch (chan->move_role) {
52008eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
52018eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
52028eb200bdSMat Martineau 					       remote_amp_id);
52038eb200bdSMat Martineau 			break;
52048eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
52058eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
52068eb200bdSMat Martineau 			break;
52078eb200bdSMat Martineau 		default:
52088eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
52098eb200bdSMat Martineau 			break;
52108eb200bdSMat Martineau 		}
52118eb200bdSMat Martineau 	}
52128eb200bdSMat Martineau }
52138eb200bdSMat Martineau 
52148d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5215ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5216ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
52178d5a04a1SMat Martineau {
52188d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
52191500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
522002b0fbb9SMat Martineau 	struct l2cap_chan *chan;
52218d5a04a1SMat Martineau 	u16 icid = 0;
52228d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
52238d5a04a1SMat Martineau 
52248d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
52258d5a04a1SMat Martineau 		return -EPROTO;
52268d5a04a1SMat Martineau 
52278d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
52288d5a04a1SMat Martineau 
5229ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
52308d5a04a1SMat Martineau 
52310bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
52328d5a04a1SMat Martineau 		return -EINVAL;
52338d5a04a1SMat Martineau 
523402b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
523502b0fbb9SMat Martineau 	if (!chan) {
52361500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
5237dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
52381500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
52391500109bSMat Martineau 			       sizeof(rsp), &rsp);
524002b0fbb9SMat Martineau 		return 0;
524102b0fbb9SMat Martineau 	}
524202b0fbb9SMat Martineau 
52431500109bSMat Martineau 	chan->ident = cmd->ident;
52441500109bSMat Martineau 
524502b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
524602b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
524702b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
524802b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
524902b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
525002b0fbb9SMat Martineau 		goto send_move_response;
525102b0fbb9SMat Martineau 	}
525202b0fbb9SMat Martineau 
525302b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
525402b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
525502b0fbb9SMat Martineau 		goto send_move_response;
525602b0fbb9SMat Martineau 	}
525702b0fbb9SMat Martineau 
52586ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
525902b0fbb9SMat Martineau 		struct hci_dev *hdev;
526002b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
526102b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
526202b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
526302b0fbb9SMat Martineau 			if (hdev)
526402b0fbb9SMat Martineau 				hci_dev_put(hdev);
526502b0fbb9SMat Martineau 
526602b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
526702b0fbb9SMat Martineau 			goto send_move_response;
526802b0fbb9SMat Martineau 		}
526902b0fbb9SMat Martineau 		hci_dev_put(hdev);
527002b0fbb9SMat Martineau 	}
527102b0fbb9SMat Martineau 
527202b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
527302b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
527402b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
527502b0fbb9SMat Martineau 	 */
527602b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
527702b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
52786f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
527902b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
528002b0fbb9SMat Martineau 		goto send_move_response;
528102b0fbb9SMat Martineau 	}
528202b0fbb9SMat Martineau 
528302b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
528402b0fbb9SMat Martineau 	l2cap_move_setup(chan);
528502b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
528602b0fbb9SMat Martineau 
52876ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
528802b0fbb9SMat Martineau 		/* Moving to BR/EDR */
528902b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
529002b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
529102b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
529202b0fbb9SMat Martineau 		} else {
529302b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
529402b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
529502b0fbb9SMat Martineau 		}
529602b0fbb9SMat Martineau 	} else {
529702b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
529802b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
529902b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
530002b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
530102b0fbb9SMat Martineau 	}
530202b0fbb9SMat Martineau 
530302b0fbb9SMat Martineau send_move_response:
53041500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
53058d5a04a1SMat Martineau 
530602b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
530702b0fbb9SMat Martineau 
53088d5a04a1SMat Martineau 	return 0;
53098d5a04a1SMat Martineau }
53108d5a04a1SMat Martineau 
53115b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
53125b155ef9SMat Martineau {
53135b155ef9SMat Martineau 	struct l2cap_chan *chan;
53145b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
53155b155ef9SMat Martineau 
53165b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53175b155ef9SMat Martineau 	if (!chan) {
53185b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
53195b155ef9SMat Martineau 		return;
53205b155ef9SMat Martineau 	}
53215b155ef9SMat Martineau 
53225b155ef9SMat Martineau 	__clear_chan_timer(chan);
53235b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
53245b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
53255b155ef9SMat Martineau 
53265b155ef9SMat Martineau 	switch (chan->move_state) {
53275b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
53285b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
53295b155ef9SMat Martineau 		 * is complete.
53305b155ef9SMat Martineau 		 */
53315b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
53325b155ef9SMat Martineau 		break;
53335b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
53345b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
53355b155ef9SMat Martineau 			break;
53365b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
53375b155ef9SMat Martineau 				    &chan->conn_state)) {
53385b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
53395b155ef9SMat Martineau 		} else {
53405b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
53415b155ef9SMat Martineau 			 * proceed with move
53425b155ef9SMat Martineau 			 */
53435b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
53445b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
53455b155ef9SMat Martineau 		}
53465b155ef9SMat Martineau 		break;
53475b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
53485b155ef9SMat Martineau 		/* Moving to AMP */
53495b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
53505b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
53515b155ef9SMat Martineau 			 * after logical link is ready
53525b155ef9SMat Martineau 			 */
53535b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
53545b155ef9SMat Martineau 		} else {
53555b155ef9SMat Martineau 			/* Both logical link and move success
53565b155ef9SMat Martineau 			 * are required to confirm
53575b155ef9SMat Martineau 			 */
53585b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
53595b155ef9SMat Martineau 		}
53605b155ef9SMat Martineau 
53615b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
53625b155ef9SMat Martineau 		if (!hchan) {
53635b155ef9SMat Martineau 			/* Logical link not available */
53645b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
53655b155ef9SMat Martineau 			break;
53665b155ef9SMat Martineau 		}
53675b155ef9SMat Martineau 
53685b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
53695b155ef9SMat Martineau 		 * send confirmation.
53705b155ef9SMat Martineau 		 */
53715b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
53725b155ef9SMat Martineau 			break;
53735b155ef9SMat Martineau 
53745b155ef9SMat Martineau 		/* Logical link is already ready to go */
53755b155ef9SMat Martineau 
53765b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
53775b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
53785b155ef9SMat Martineau 
53795b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
53805b155ef9SMat Martineau 			/* Can confirm now */
53815b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
53825b155ef9SMat Martineau 		} else {
53835b155ef9SMat Martineau 			/* Now only need move success
53845b155ef9SMat Martineau 			 * to confirm
53855b155ef9SMat Martineau 			 */
53865b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
53875b155ef9SMat Martineau 		}
53885b155ef9SMat Martineau 
53895b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
53905b155ef9SMat Martineau 		break;
53915b155ef9SMat Martineau 	default:
53925b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
53935b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
53945b155ef9SMat Martineau 		l2cap_move_done(chan);
53955b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
53965b155ef9SMat Martineau 	}
53975b155ef9SMat Martineau 
53985b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
53995b155ef9SMat Martineau }
54005b155ef9SMat Martineau 
54015b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
54025b155ef9SMat Martineau 			    u16 result)
54035b155ef9SMat Martineau {
54045b155ef9SMat Martineau 	struct l2cap_chan *chan;
54055b155ef9SMat Martineau 
54065b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
54075b155ef9SMat Martineau 	if (!chan) {
54085b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
54095b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
54105b155ef9SMat Martineau 		return;
54115b155ef9SMat Martineau 	}
54125b155ef9SMat Martineau 
54135b155ef9SMat Martineau 	__clear_chan_timer(chan);
54145b155ef9SMat Martineau 
54155b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
54165b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
54175b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
54185b155ef9SMat Martineau 		} else {
54195b155ef9SMat Martineau 			/* Cleanup - cancel move */
54205b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
54215b155ef9SMat Martineau 			l2cap_move_done(chan);
54225b155ef9SMat Martineau 		}
54235b155ef9SMat Martineau 	}
54245b155ef9SMat Martineau 
54255b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
54265b155ef9SMat Martineau 
54275b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
54285b155ef9SMat Martineau }
54295b155ef9SMat Martineau 
54305b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5431ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5432ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
54338d5a04a1SMat Martineau {
54348d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
54358d5a04a1SMat Martineau 	u16 icid, result;
54368d5a04a1SMat Martineau 
54378d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
54388d5a04a1SMat Martineau 		return -EPROTO;
54398d5a04a1SMat Martineau 
54408d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
54418d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
54428d5a04a1SMat Martineau 
5443ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
54448d5a04a1SMat Martineau 
54455b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
54465b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
54475b155ef9SMat Martineau 	else
54485b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
54498d5a04a1SMat Martineau 
54508d5a04a1SMat Martineau 	return 0;
54518d5a04a1SMat Martineau }
54528d5a04a1SMat Martineau 
54535f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5454ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5455ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
54568d5a04a1SMat Martineau {
54578d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
54585f3847a4SMat Martineau 	struct l2cap_chan *chan;
54598d5a04a1SMat Martineau 	u16 icid, result;
54608d5a04a1SMat Martineau 
54618d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
54628d5a04a1SMat Martineau 		return -EPROTO;
54638d5a04a1SMat Martineau 
54648d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
54658d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
54668d5a04a1SMat Martineau 
5467ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
54688d5a04a1SMat Martineau 
54695f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
54705f3847a4SMat Martineau 	if (!chan) {
54715f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
54728d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
54735f3847a4SMat Martineau 		return 0;
54745f3847a4SMat Martineau 	}
54755f3847a4SMat Martineau 
54765f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
54775f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
54785f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
54796ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
54805f3847a4SMat Martineau 				__release_logical_link(chan);
54815f3847a4SMat Martineau 		} else {
54825f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
54835f3847a4SMat Martineau 		}
54845f3847a4SMat Martineau 
54855f3847a4SMat Martineau 		l2cap_move_done(chan);
54865f3847a4SMat Martineau 	}
54875f3847a4SMat Martineau 
54885f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
54895f3847a4SMat Martineau 
54905f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
54918d5a04a1SMat Martineau 
54928d5a04a1SMat Martineau 	return 0;
54938d5a04a1SMat Martineau }
54948d5a04a1SMat Martineau 
54958d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5496ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5497ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
54988d5a04a1SMat Martineau {
54998d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
55003fd71a0aSMat Martineau 	struct l2cap_chan *chan;
55018d5a04a1SMat Martineau 	u16 icid;
55028d5a04a1SMat Martineau 
55038d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
55048d5a04a1SMat Martineau 		return -EPROTO;
55058d5a04a1SMat Martineau 
55068d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
55078d5a04a1SMat Martineau 
5508ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
55098d5a04a1SMat Martineau 
55103fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
55113fd71a0aSMat Martineau 	if (!chan)
55123fd71a0aSMat Martineau 		return 0;
55133fd71a0aSMat Martineau 
55143fd71a0aSMat Martineau 	__clear_chan_timer(chan);
55153fd71a0aSMat Martineau 
55163fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
55173fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
55183fd71a0aSMat Martineau 
55196ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
55203fd71a0aSMat Martineau 			__release_logical_link(chan);
55213fd71a0aSMat Martineau 
55223fd71a0aSMat Martineau 		l2cap_move_done(chan);
55233fd71a0aSMat Martineau 	}
55243fd71a0aSMat Martineau 
55253fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
55263fd71a0aSMat Martineau 
55278d5a04a1SMat Martineau 	return 0;
55288d5a04a1SMat Martineau }
55298d5a04a1SMat Martineau 
5530de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
55312d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5532203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5533de73115aSClaudio Takahasi {
5534de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5535de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5536de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5537203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
55382ce603ebSClaudio Takahasi 	int err;
5539de73115aSClaudio Takahasi 
554040bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
5541de73115aSClaudio Takahasi 		return -EINVAL;
5542de73115aSClaudio Takahasi 
5543de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5544de73115aSClaudio Takahasi 		return -EPROTO;
5545de73115aSClaudio Takahasi 
5546de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5547de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5548de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5549de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5550de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5551de73115aSClaudio Takahasi 
5552de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5553de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5554de73115aSClaudio Takahasi 
5555de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
55562ce603ebSClaudio Takahasi 
5557d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
55582ce603ebSClaudio Takahasi 	if (err)
5559dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5560de73115aSClaudio Takahasi 	else
5561dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5562de73115aSClaudio Takahasi 
5563de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5564de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5565de73115aSClaudio Takahasi 
5566ffb5a827SAndre Guedes 	if (!err) {
5567f4869e2aSJohan Hedberg 		u8 store_hint;
5568ffb5a827SAndre Guedes 
5569f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
5570f4869e2aSJohan Hedberg 						to_multiplier);
5571f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
5572f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
5573f4869e2aSJohan Hedberg 				    to_multiplier);
5574f4869e2aSJohan Hedberg 
5575ffb5a827SAndre Guedes 	}
55762ce603ebSClaudio Takahasi 
5577de73115aSClaudio Takahasi 	return 0;
5578de73115aSClaudio Takahasi }
5579de73115aSClaudio Takahasi 
5580f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5581f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5582f1496deeSJohan Hedberg 				u8 *data)
5583f1496deeSJohan Hedberg {
5584f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
55853e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
5586f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5587f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
55883e64b7bdSJohan Hedberg 	int err, sec_level;
5589f1496deeSJohan Hedberg 
5590f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5591f1496deeSJohan Hedberg 		return -EPROTO;
5592f1496deeSJohan Hedberg 
5593f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5594f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5595f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5596f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5597f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5598f1496deeSJohan Hedberg 
5599571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
560040624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
560140624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
5602f1496deeSJohan Hedberg 		return -EPROTO;
5603f1496deeSJohan Hedberg 
5604f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5605f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5606f1496deeSJohan Hedberg 
5607f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5608f1496deeSJohan Hedberg 
5609f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5610f1496deeSJohan Hedberg 	if (!chan) {
5611f1496deeSJohan Hedberg 		err = -EBADSLT;
5612f1496deeSJohan Hedberg 		goto unlock;
5613f1496deeSJohan Hedberg 	}
5614f1496deeSJohan Hedberg 
5615f1496deeSJohan Hedberg 	err = 0;
5616f1496deeSJohan Hedberg 
5617f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5618f1496deeSJohan Hedberg 
5619f1496deeSJohan Hedberg 	switch (result) {
5620571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
562140624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
562240624183SJohan Hedberg 			err = -EBADSLT;
562340624183SJohan Hedberg 			break;
562440624183SJohan Hedberg 		}
562540624183SJohan Hedberg 
5626f1496deeSJohan Hedberg 		chan->ident = 0;
5627f1496deeSJohan Hedberg 		chan->dcid = dcid;
5628f1496deeSJohan Hedberg 		chan->omtu = mtu;
5629f1496deeSJohan Hedberg 		chan->remote_mps = mps;
56300cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5631f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5632f1496deeSJohan Hedberg 		break;
5633f1496deeSJohan Hedberg 
5634571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
5635571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
56363e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
56373e64b7bdSJohan Hedberg 		 * anything.
56383e64b7bdSJohan Hedberg 		 */
56393e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
56403e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
56413e64b7bdSJohan Hedberg 			break;
56423e64b7bdSJohan Hedberg 		}
56433e64b7bdSJohan Hedberg 
56443e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
56453e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
56463e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
56473e64b7bdSJohan Hedberg 
56483e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
56493e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
56503e64b7bdSJohan Hedberg 
56513e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
56523e64b7bdSJohan Hedberg 		break;
56533e64b7bdSJohan Hedberg 
5654f1496deeSJohan Hedberg 	default:
5655f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5656f1496deeSJohan Hedberg 		break;
5657f1496deeSJohan Hedberg 	}
5658f1496deeSJohan Hedberg 
5659f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5660f1496deeSJohan Hedberg 
5661f1496deeSJohan Hedberg unlock:
5662f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5663f1496deeSJohan Hedberg 
5664f1496deeSJohan Hedberg 	return err;
5665f1496deeSJohan Hedberg }
5666f1496deeSJohan Hedberg 
56673300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
56682d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
56692d792818SGustavo Padovan 				      u8 *data)
56703300d9a9SClaudio Takahasi {
56713300d9a9SClaudio Takahasi 	int err = 0;
56723300d9a9SClaudio Takahasi 
56733300d9a9SClaudio Takahasi 	switch (cmd->code) {
56743300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5675cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
56763300d9a9SClaudio Takahasi 		break;
56773300d9a9SClaudio Takahasi 
56783300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5679cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
56803300d9a9SClaudio Takahasi 		break;
56813300d9a9SClaudio Takahasi 
56823300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5683f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
56849245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
56853300d9a9SClaudio Takahasi 		break;
56863300d9a9SClaudio Takahasi 
56873300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
56883300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
56893300d9a9SClaudio Takahasi 		break;
56903300d9a9SClaudio Takahasi 
56913300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
56929245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
56933300d9a9SClaudio Takahasi 		break;
56943300d9a9SClaudio Takahasi 
56953300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5696cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
56973300d9a9SClaudio Takahasi 		break;
56983300d9a9SClaudio Takahasi 
56993300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
57009245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
57013300d9a9SClaudio Takahasi 		break;
57023300d9a9SClaudio Takahasi 
57033300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
57043300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
57053300d9a9SClaudio Takahasi 		break;
57063300d9a9SClaudio Takahasi 
57073300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
57083300d9a9SClaudio Takahasi 		break;
57093300d9a9SClaudio Takahasi 
57103300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5711cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
57123300d9a9SClaudio Takahasi 		break;
57133300d9a9SClaudio Takahasi 
57143300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
57159245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
57163300d9a9SClaudio Takahasi 		break;
57173300d9a9SClaudio Takahasi 
5718f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5719f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5720f94ff6ffSMat Martineau 		break;
5721f94ff6ffSMat Martineau 
57228d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
57238d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
57248d5a04a1SMat Martineau 		break;
57258d5a04a1SMat Martineau 
57268d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
57279245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
57288d5a04a1SMat Martineau 		break;
57298d5a04a1SMat Martineau 
57308d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
57318d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
57328d5a04a1SMat Martineau 		break;
57338d5a04a1SMat Martineau 
57348d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
57359245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
57368d5a04a1SMat Martineau 		break;
57378d5a04a1SMat Martineau 
57383300d9a9SClaudio Takahasi 	default:
57393300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
57403300d9a9SClaudio Takahasi 		err = -EINVAL;
57413300d9a9SClaudio Takahasi 		break;
57423300d9a9SClaudio Takahasi 	}
57433300d9a9SClaudio Takahasi 
57443300d9a9SClaudio Takahasi 	return err;
57453300d9a9SClaudio Takahasi }
57463300d9a9SClaudio Takahasi 
574727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
574827e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
574927e2d4c8SJohan Hedberg 				u8 *data)
575027e2d4c8SJohan Hedberg {
575127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
575227e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
575327e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
57540cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
575527e2d4c8SJohan Hedberg 	__le16 psm;
575627e2d4c8SJohan Hedberg 	u8 result;
575727e2d4c8SJohan Hedberg 
575827e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
575927e2d4c8SJohan Hedberg 		return -EPROTO;
576027e2d4c8SJohan Hedberg 
576127e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
576227e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
576327e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
576427e2d4c8SJohan Hedberg 	psm  = req->psm;
576527e2d4c8SJohan Hedberg 	dcid = 0;
57660cd75f7eSJohan Hedberg 	credits = 0;
576727e2d4c8SJohan Hedberg 
576827e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
576927e2d4c8SJohan Hedberg 		return -EPROTO;
577027e2d4c8SJohan Hedberg 
577127e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
577227e2d4c8SJohan Hedberg 	       scid, mtu, mps);
577327e2d4c8SJohan Hedberg 
577427e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
577527e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
577627e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
577727e2d4c8SJohan Hedberg 	if (!pchan) {
5778571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
577927e2d4c8SJohan Hedberg 		chan = NULL;
578027e2d4c8SJohan Hedberg 		goto response;
578127e2d4c8SJohan Hedberg 	}
578227e2d4c8SJohan Hedberg 
578327e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
578427e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
578527e2d4c8SJohan Hedberg 
578635dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
578735dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
5788571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
578927e2d4c8SJohan Hedberg 		chan = NULL;
579027e2d4c8SJohan Hedberg 		goto response_unlock;
579127e2d4c8SJohan Hedberg 	}
579227e2d4c8SJohan Hedberg 
57938a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
57948a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
5795571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
57968a7889ccSJohan Hedberg 		chan = NULL;
57978a7889ccSJohan Hedberg 		goto response_unlock;
57988a7889ccSJohan Hedberg 	}
57998a7889ccSJohan Hedberg 
580027e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
580127e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
5802571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
580327e2d4c8SJohan Hedberg 		chan = NULL;
580427e2d4c8SJohan Hedberg 		goto response_unlock;
580527e2d4c8SJohan Hedberg 	}
580627e2d4c8SJohan Hedberg 
580727e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
580827e2d4c8SJohan Hedberg 	if (!chan) {
5809571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
581027e2d4c8SJohan Hedberg 		goto response_unlock;
581127e2d4c8SJohan Hedberg 	}
581227e2d4c8SJohan Hedberg 
581327e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
581427e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
5815a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
5816a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
581727e2d4c8SJohan Hedberg 	chan->psm  = psm;
581827e2d4c8SJohan Hedberg 	chan->dcid = scid;
581927e2d4c8SJohan Hedberg 	chan->omtu = mtu;
582027e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
582127e2d4c8SJohan Hedberg 
582227e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
5823fe149310SLuiz Augusto von Dentz 
5824ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
5825fe149310SLuiz Augusto von Dentz 
582627e2d4c8SJohan Hedberg 	dcid = chan->scid;
58270cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
582827e2d4c8SJohan Hedberg 
582927e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
583027e2d4c8SJohan Hedberg 
583127e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
583227e2d4c8SJohan Hedberg 
583327e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
583427e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
5835434714dcSJohan Hedberg 		/* The following result value is actually not defined
5836434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
5837434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
5838434714dcSJohan Hedberg 		 * instead of sending a response.
5839434714dcSJohan Hedberg 		 */
584027e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
584127e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
584227e2d4c8SJohan Hedberg 	} else {
584327e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
5844571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
584527e2d4c8SJohan Hedberg 	}
584627e2d4c8SJohan Hedberg 
584727e2d4c8SJohan Hedberg response_unlock:
584827e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
584927e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5850a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
585127e2d4c8SJohan Hedberg 
585227e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
585327e2d4c8SJohan Hedberg 		return 0;
585427e2d4c8SJohan Hedberg 
585527e2d4c8SJohan Hedberg response:
585627e2d4c8SJohan Hedberg 	if (chan) {
585727e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
58583916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
585927e2d4c8SJohan Hedberg 	} else {
586027e2d4c8SJohan Hedberg 		rsp.mtu = 0;
586127e2d4c8SJohan Hedberg 		rsp.mps = 0;
586227e2d4c8SJohan Hedberg 	}
586327e2d4c8SJohan Hedberg 
586427e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
58650cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
586627e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
586727e2d4c8SJohan Hedberg 
586827e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
586927e2d4c8SJohan Hedberg 
587027e2d4c8SJohan Hedberg 	return 0;
587127e2d4c8SJohan Hedberg }
587227e2d4c8SJohan Hedberg 
5873fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5874fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5875fad5fc89SJohan Hedberg 				   u8 *data)
5876fad5fc89SJohan Hedberg {
5877fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5878fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
58790f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
5880fad5fc89SJohan Hedberg 
5881fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5882fad5fc89SJohan Hedberg 		return -EPROTO;
5883fad5fc89SJohan Hedberg 
5884fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5885fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5886fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5887fad5fc89SJohan Hedberg 
5888fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5889fad5fc89SJohan Hedberg 
5890fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5891fad5fc89SJohan Hedberg 	if (!chan)
5892fad5fc89SJohan Hedberg 		return -EBADSLT;
5893fad5fc89SJohan Hedberg 
58940f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
58950f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
58960f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
58970f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
5898ee93053dSMartin Townsend 		l2cap_chan_unlock(chan);
58990f1bfe4eSJohan Hedberg 
59000f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
59010f1bfe4eSJohan Hedberg 		 * command reject packet.
59020f1bfe4eSJohan Hedberg 		 */
59030f1bfe4eSJohan Hedberg 		return 0;
59040f1bfe4eSJohan Hedberg 	}
59050f1bfe4eSJohan Hedberg 
5906fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5907fad5fc89SJohan Hedberg 
59088a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
59098a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
5910fad5fc89SJohan Hedberg 
5911fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5912fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5913fad5fc89SJohan Hedberg 
5914fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5915fad5fc89SJohan Hedberg 
5916fad5fc89SJohan Hedberg 	return 0;
5917fad5fc89SJohan Hedberg }
5918fad5fc89SJohan Hedberg 
591915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
592015f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
592115f02b91SLuiz Augusto von Dentz 				       u8 *data)
592215f02b91SLuiz Augusto von Dentz {
592315f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_req *req = (void *) data;
592415f02b91SLuiz Augusto von Dentz 	struct {
592515f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
59267cf3b1ddSLuiz Augusto von Dentz 		__le16 dcid[L2CAP_ECRED_MAX_CID];
592715f02b91SLuiz Augusto von Dentz 	} __packed pdu;
592815f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *pchan;
5929965995b7SYueHaibing 	u16 mtu, mps;
593015f02b91SLuiz Augusto von Dentz 	__le16 psm;
593115f02b91SLuiz Augusto von Dentz 	u8 result, len = 0;
593215f02b91SLuiz Augusto von Dentz 	int i, num_scid;
593315f02b91SLuiz Augusto von Dentz 	bool defer = false;
593415f02b91SLuiz Augusto von Dentz 
59354be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
59364be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
59374be5ca67SLuiz Augusto von Dentz 
593869d67b46SKonstantin Forostyan 	if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
593915f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
594015f02b91SLuiz Augusto von Dentz 		goto response;
594115f02b91SLuiz Augusto von Dentz 	}
594215f02b91SLuiz Augusto von Dentz 
59437cf3b1ddSLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
59447cf3b1ddSLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
59457cf3b1ddSLuiz Augusto von Dentz 
59467cf3b1ddSLuiz Augusto von Dentz 	if (num_scid > ARRAY_SIZE(pdu.dcid)) {
59477cf3b1ddSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
59487cf3b1ddSLuiz Augusto von Dentz 		goto response;
59497cf3b1ddSLuiz Augusto von Dentz 	}
59507cf3b1ddSLuiz Augusto von Dentz 
595115f02b91SLuiz Augusto von Dentz 	mtu  = __le16_to_cpu(req->mtu);
595215f02b91SLuiz Augusto von Dentz 	mps  = __le16_to_cpu(req->mps);
595315f02b91SLuiz Augusto von Dentz 
595415f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
595515f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_UNACCEPT_PARAMS;
595615f02b91SLuiz Augusto von Dentz 		goto response;
595715f02b91SLuiz Augusto von Dentz 	}
595815f02b91SLuiz Augusto von Dentz 
595915f02b91SLuiz Augusto von Dentz 	psm  = req->psm;
596015f02b91SLuiz Augusto von Dentz 
596115f02b91SLuiz Augusto von Dentz 	BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
596215f02b91SLuiz Augusto von Dentz 
596315f02b91SLuiz Augusto von Dentz 	memset(&pdu, 0, sizeof(pdu));
596415f02b91SLuiz Augusto von Dentz 
596515f02b91SLuiz Augusto von Dentz 	/* Check if we have socket listening on psm */
596615f02b91SLuiz Augusto von Dentz 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
596715f02b91SLuiz Augusto von Dentz 					 &conn->hcon->dst, LE_LINK);
596815f02b91SLuiz Augusto von Dentz 	if (!pchan) {
596915f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
597015f02b91SLuiz Augusto von Dentz 		goto response;
597115f02b91SLuiz Augusto von Dentz 	}
597215f02b91SLuiz Augusto von Dentz 
597315f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
597415f02b91SLuiz Augusto von Dentz 	l2cap_chan_lock(pchan);
597515f02b91SLuiz Augusto von Dentz 
597615f02b91SLuiz Augusto von Dentz 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
597715f02b91SLuiz Augusto von Dentz 				     SMP_ALLOW_STK)) {
597815f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHENTICATION;
597915f02b91SLuiz Augusto von Dentz 		goto unlock;
598015f02b91SLuiz Augusto von Dentz 	}
598115f02b91SLuiz Augusto von Dentz 
598215f02b91SLuiz Augusto von Dentz 	result = L2CAP_CR_LE_SUCCESS;
598315f02b91SLuiz Augusto von Dentz 
598415f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
598515f02b91SLuiz Augusto von Dentz 		u16 scid = __le16_to_cpu(req->scid[i]);
598615f02b91SLuiz Augusto von Dentz 
598715f02b91SLuiz Augusto von Dentz 		BT_DBG("scid[%d] 0x%4.4x", i, scid);
598815f02b91SLuiz Augusto von Dentz 
598915f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = 0x0000;
599015f02b91SLuiz Augusto von Dentz 		len += sizeof(*pdu.dcid);
599115f02b91SLuiz Augusto von Dentz 
599215f02b91SLuiz Augusto von Dentz 		/* Check for valid dynamic CID range */
599315f02b91SLuiz Augusto von Dentz 		if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
599415f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_INVALID_SCID;
599515f02b91SLuiz Augusto von Dentz 			continue;
599615f02b91SLuiz Augusto von Dentz 		}
599715f02b91SLuiz Augusto von Dentz 
599815f02b91SLuiz Augusto von Dentz 		/* Check if we already have channel with that dcid */
599915f02b91SLuiz Augusto von Dentz 		if (__l2cap_get_chan_by_dcid(conn, scid)) {
600015f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_SCID_IN_USE;
600115f02b91SLuiz Augusto von Dentz 			continue;
600215f02b91SLuiz Augusto von Dentz 		}
600315f02b91SLuiz Augusto von Dentz 
600415f02b91SLuiz Augusto von Dentz 		chan = pchan->ops->new_connection(pchan);
600515f02b91SLuiz Augusto von Dentz 		if (!chan) {
600615f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_NO_MEM;
600715f02b91SLuiz Augusto von Dentz 			continue;
600815f02b91SLuiz Augusto von Dentz 		}
600915f02b91SLuiz Augusto von Dentz 
601015f02b91SLuiz Augusto von Dentz 		bacpy(&chan->src, &conn->hcon->src);
601115f02b91SLuiz Augusto von Dentz 		bacpy(&chan->dst, &conn->hcon->dst);
601215f02b91SLuiz Augusto von Dentz 		chan->src_type = bdaddr_src_type(conn->hcon);
601315f02b91SLuiz Augusto von Dentz 		chan->dst_type = bdaddr_dst_type(conn->hcon);
601415f02b91SLuiz Augusto von Dentz 		chan->psm  = psm;
601515f02b91SLuiz Augusto von Dentz 		chan->dcid = scid;
601615f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
601715f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
601815f02b91SLuiz Augusto von Dentz 
601915f02b91SLuiz Augusto von Dentz 		__l2cap_chan_add(conn, chan);
602015f02b91SLuiz Augusto von Dentz 
602115f02b91SLuiz Augusto von Dentz 		l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
602215f02b91SLuiz Augusto von Dentz 
602315f02b91SLuiz Augusto von Dentz 		/* Init response */
602415f02b91SLuiz Augusto von Dentz 		if (!pdu.rsp.credits) {
602515f02b91SLuiz Augusto von Dentz 			pdu.rsp.mtu = cpu_to_le16(chan->imtu);
602615f02b91SLuiz Augusto von Dentz 			pdu.rsp.mps = cpu_to_le16(chan->mps);
602715f02b91SLuiz Augusto von Dentz 			pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
602815f02b91SLuiz Augusto von Dentz 		}
602915f02b91SLuiz Augusto von Dentz 
603015f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = cpu_to_le16(chan->scid);
603115f02b91SLuiz Augusto von Dentz 
603215f02b91SLuiz Augusto von Dentz 		__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
603315f02b91SLuiz Augusto von Dentz 
603415f02b91SLuiz Augusto von Dentz 		chan->ident = cmd->ident;
603515f02b91SLuiz Augusto von Dentz 
603615f02b91SLuiz Augusto von Dentz 		if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
603715f02b91SLuiz Augusto von Dentz 			l2cap_state_change(chan, BT_CONNECT2);
603815f02b91SLuiz Augusto von Dentz 			defer = true;
603915f02b91SLuiz Augusto von Dentz 			chan->ops->defer(chan);
604015f02b91SLuiz Augusto von Dentz 		} else {
604115f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
604215f02b91SLuiz Augusto von Dentz 		}
604315f02b91SLuiz Augusto von Dentz 	}
604415f02b91SLuiz Augusto von Dentz 
604515f02b91SLuiz Augusto von Dentz unlock:
604615f02b91SLuiz Augusto von Dentz 	l2cap_chan_unlock(pchan);
604715f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
604815f02b91SLuiz Augusto von Dentz 	l2cap_chan_put(pchan);
604915f02b91SLuiz Augusto von Dentz 
605015f02b91SLuiz Augusto von Dentz response:
605115f02b91SLuiz Augusto von Dentz 	pdu.rsp.result = cpu_to_le16(result);
605215f02b91SLuiz Augusto von Dentz 
605315f02b91SLuiz Augusto von Dentz 	if (defer)
605415f02b91SLuiz Augusto von Dentz 		return 0;
605515f02b91SLuiz Augusto von Dentz 
605615f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
605715f02b91SLuiz Augusto von Dentz 		       sizeof(pdu.rsp) + len, &pdu);
605815f02b91SLuiz Augusto von Dentz 
605915f02b91SLuiz Augusto von Dentz 	return 0;
606015f02b91SLuiz Augusto von Dentz }
606115f02b91SLuiz Augusto von Dentz 
606215f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
606315f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
606415f02b91SLuiz Augusto von Dentz 				       u8 *data)
606515f02b91SLuiz Augusto von Dentz {
606615f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
606715f02b91SLuiz Augusto von Dentz 	struct hci_conn *hcon = conn->hcon;
606815f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, credits, result;
606915f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
607015f02b91SLuiz Augusto von Dentz 	int err = 0, sec_level;
607115f02b91SLuiz Augusto von Dentz 	int i = 0;
607215f02b91SLuiz Augusto von Dentz 
607315f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
607415f02b91SLuiz Augusto von Dentz 		return -EPROTO;
607515f02b91SLuiz Augusto von Dentz 
607615f02b91SLuiz Augusto von Dentz 	mtu     = __le16_to_cpu(rsp->mtu);
607715f02b91SLuiz Augusto von Dentz 	mps     = __le16_to_cpu(rsp->mps);
607815f02b91SLuiz Augusto von Dentz 	credits = __le16_to_cpu(rsp->credits);
607915f02b91SLuiz Augusto von Dentz 	result  = __le16_to_cpu(rsp->result);
608015f02b91SLuiz Augusto von Dentz 
608115f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
608215f02b91SLuiz Augusto von Dentz 	       result);
608315f02b91SLuiz Augusto von Dentz 
608415f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
608515f02b91SLuiz Augusto von Dentz 
608615f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*rsp);
608715f02b91SLuiz Augusto von Dentz 
608815f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
608915f02b91SLuiz Augusto von Dentz 		u16 dcid;
609015f02b91SLuiz Augusto von Dentz 
609115f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident ||
609215f02b91SLuiz Augusto von Dentz 		    chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
609315f02b91SLuiz Augusto von Dentz 		    chan->state == BT_CONNECTED)
609415f02b91SLuiz Augusto von Dentz 			continue;
609515f02b91SLuiz Augusto von Dentz 
609615f02b91SLuiz Augusto von Dentz 		l2cap_chan_lock(chan);
609715f02b91SLuiz Augusto von Dentz 
609815f02b91SLuiz Augusto von Dentz 		/* Check that there is a dcid for each pending channel */
609915f02b91SLuiz Augusto von Dentz 		if (cmd_len < sizeof(dcid)) {
610015f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
610115f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
610215f02b91SLuiz Augusto von Dentz 			continue;
610315f02b91SLuiz Augusto von Dentz 		}
610415f02b91SLuiz Augusto von Dentz 
610515f02b91SLuiz Augusto von Dentz 		dcid = __le16_to_cpu(rsp->dcid[i++]);
610615f02b91SLuiz Augusto von Dentz 		cmd_len -= sizeof(u16);
610715f02b91SLuiz Augusto von Dentz 
610815f02b91SLuiz Augusto von Dentz 		BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
610915f02b91SLuiz Augusto von Dentz 
611015f02b91SLuiz Augusto von Dentz 		/* Check if dcid is already in use */
611115f02b91SLuiz Augusto von Dentz 		if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
611215f02b91SLuiz Augusto von Dentz 			/* If a device receives a
611315f02b91SLuiz Augusto von Dentz 			 * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
611415f02b91SLuiz Augusto von Dentz 			 * already-assigned Destination CID, then both the
611515f02b91SLuiz Augusto von Dentz 			 * original channel and the new channel shall be
611615f02b91SLuiz Augusto von Dentz 			 * immediately discarded and not used.
611715f02b91SLuiz Augusto von Dentz 			 */
611815f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
611915f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
612015f02b91SLuiz Augusto von Dentz 			chan = __l2cap_get_chan_by_dcid(conn, dcid);
612115f02b91SLuiz Augusto von Dentz 			l2cap_chan_lock(chan);
612215f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNRESET);
612315f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
612415f02b91SLuiz Augusto von Dentz 			continue;
612515f02b91SLuiz Augusto von Dentz 		}
612615f02b91SLuiz Augusto von Dentz 
612715f02b91SLuiz Augusto von Dentz 		switch (result) {
612815f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_AUTHENTICATION:
612915f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_ENCRYPTION:
613015f02b91SLuiz Augusto von Dentz 			/* If we already have MITM protection we can't do
613115f02b91SLuiz Augusto von Dentz 			 * anything.
613215f02b91SLuiz Augusto von Dentz 			 */
613315f02b91SLuiz Augusto von Dentz 			if (hcon->sec_level > BT_SECURITY_MEDIUM) {
613415f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
613515f02b91SLuiz Augusto von Dentz 				break;
613615f02b91SLuiz Augusto von Dentz 			}
613715f02b91SLuiz Augusto von Dentz 
613815f02b91SLuiz Augusto von Dentz 			sec_level = hcon->sec_level + 1;
613915f02b91SLuiz Augusto von Dentz 			if (chan->sec_level < sec_level)
614015f02b91SLuiz Augusto von Dentz 				chan->sec_level = sec_level;
614115f02b91SLuiz Augusto von Dentz 
614215f02b91SLuiz Augusto von Dentz 			/* We'll need to send a new Connect Request */
614315f02b91SLuiz Augusto von Dentz 			clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
614415f02b91SLuiz Augusto von Dentz 
614515f02b91SLuiz Augusto von Dentz 			smp_conn_security(hcon, chan->sec_level);
614615f02b91SLuiz Augusto von Dentz 			break;
614715f02b91SLuiz Augusto von Dentz 
614815f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_BAD_PSM:
614915f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
615015f02b91SLuiz Augusto von Dentz 			break;
615115f02b91SLuiz Augusto von Dentz 
615215f02b91SLuiz Augusto von Dentz 		default:
615315f02b91SLuiz Augusto von Dentz 			/* If dcid was not set it means channels was refused */
615415f02b91SLuiz Augusto von Dentz 			if (!dcid) {
615515f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
615615f02b91SLuiz Augusto von Dentz 				break;
615715f02b91SLuiz Augusto von Dentz 			}
615815f02b91SLuiz Augusto von Dentz 
615915f02b91SLuiz Augusto von Dentz 			chan->ident = 0;
616015f02b91SLuiz Augusto von Dentz 			chan->dcid = dcid;
616115f02b91SLuiz Augusto von Dentz 			chan->omtu = mtu;
616215f02b91SLuiz Augusto von Dentz 			chan->remote_mps = mps;
616315f02b91SLuiz Augusto von Dentz 			chan->tx_credits = credits;
616415f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
616515f02b91SLuiz Augusto von Dentz 			break;
616615f02b91SLuiz Augusto von Dentz 		}
616715f02b91SLuiz Augusto von Dentz 
616815f02b91SLuiz Augusto von Dentz 		l2cap_chan_unlock(chan);
616915f02b91SLuiz Augusto von Dentz 	}
617015f02b91SLuiz Augusto von Dentz 
617115f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
617215f02b91SLuiz Augusto von Dentz 
617315f02b91SLuiz Augusto von Dentz 	return err;
617415f02b91SLuiz Augusto von Dentz }
617515f02b91SLuiz Augusto von Dentz 
617615f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
617715f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
617815f02b91SLuiz Augusto von Dentz 					 u8 *data)
617915f02b91SLuiz Augusto von Dentz {
618015f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_req *req = (void *) data;
618115f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_rsp rsp;
618215f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, result;
618315f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
618415f02b91SLuiz Augusto von Dentz 	int i, num_scid;
618515f02b91SLuiz Augusto von Dentz 
61864be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
61874be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
61884be5ca67SLuiz Augusto von Dentz 
618915f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
619015f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
619115f02b91SLuiz Augusto von Dentz 		goto respond;
619215f02b91SLuiz Augusto von Dentz 	}
619315f02b91SLuiz Augusto von Dentz 
619415f02b91SLuiz Augusto von Dentz 	mtu = __le16_to_cpu(req->mtu);
619515f02b91SLuiz Augusto von Dentz 	mps = __le16_to_cpu(req->mps);
619615f02b91SLuiz Augusto von Dentz 
619715f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u", mtu, mps);
619815f02b91SLuiz Augusto von Dentz 
619915f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU) {
620015f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MTU;
620115f02b91SLuiz Augusto von Dentz 		goto respond;
620215f02b91SLuiz Augusto von Dentz 	}
620315f02b91SLuiz Augusto von Dentz 
620415f02b91SLuiz Augusto von Dentz 	if (mps < L2CAP_ECRED_MIN_MPS) {
620515f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MPS;
620615f02b91SLuiz Augusto von Dentz 		goto respond;
620715f02b91SLuiz Augusto von Dentz 	}
620815f02b91SLuiz Augusto von Dentz 
620915f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
621015f02b91SLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
621115f02b91SLuiz Augusto von Dentz 	result = L2CAP_RECONF_SUCCESS;
621215f02b91SLuiz Augusto von Dentz 
621315f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
621415f02b91SLuiz Augusto von Dentz 		u16 scid;
621515f02b91SLuiz Augusto von Dentz 
621615f02b91SLuiz Augusto von Dentz 		scid = __le16_to_cpu(req->scid[i]);
621715f02b91SLuiz Augusto von Dentz 		if (!scid)
621815f02b91SLuiz Augusto von Dentz 			return -EPROTO;
621915f02b91SLuiz Augusto von Dentz 
622015f02b91SLuiz Augusto von Dentz 		chan = __l2cap_get_chan_by_dcid(conn, scid);
622115f02b91SLuiz Augusto von Dentz 		if (!chan)
622215f02b91SLuiz Augusto von Dentz 			continue;
622315f02b91SLuiz Augusto von Dentz 
622415f02b91SLuiz Augusto von Dentz 		/* If the MTU value is decreased for any of the included
622515f02b91SLuiz Augusto von Dentz 		 * channels, then the receiver shall disconnect all
622615f02b91SLuiz Augusto von Dentz 		 * included channels.
622715f02b91SLuiz Augusto von Dentz 		 */
622815f02b91SLuiz Augusto von Dentz 		if (chan->omtu > mtu) {
622915f02b91SLuiz Augusto von Dentz 			BT_ERR("chan %p decreased MTU %u -> %u", chan,
623015f02b91SLuiz Augusto von Dentz 			       chan->omtu, mtu);
623115f02b91SLuiz Augusto von Dentz 			result = L2CAP_RECONF_INVALID_MTU;
623215f02b91SLuiz Augusto von Dentz 		}
623315f02b91SLuiz Augusto von Dentz 
623415f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
623515f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
623615f02b91SLuiz Augusto von Dentz 	}
623715f02b91SLuiz Augusto von Dentz 
623815f02b91SLuiz Augusto von Dentz respond:
623915f02b91SLuiz Augusto von Dentz 	rsp.result = cpu_to_le16(result);
624015f02b91SLuiz Augusto von Dentz 
624115f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
624215f02b91SLuiz Augusto von Dentz 		       &rsp);
624315f02b91SLuiz Augusto von Dentz 
624415f02b91SLuiz Augusto von Dentz 	return 0;
624515f02b91SLuiz Augusto von Dentz }
624615f02b91SLuiz Augusto von Dentz 
624715f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
624815f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
624915f02b91SLuiz Augusto von Dentz 					 u8 *data)
625015f02b91SLuiz Augusto von Dentz {
625115f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
625215f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
625315f02b91SLuiz Augusto von Dentz 	u16 result;
625415f02b91SLuiz Augusto von Dentz 
625515f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
625615f02b91SLuiz Augusto von Dentz 		return -EPROTO;
625715f02b91SLuiz Augusto von Dentz 
625815f02b91SLuiz Augusto von Dentz 	result = __le16_to_cpu(rsp->result);
625915f02b91SLuiz Augusto von Dentz 
626015f02b91SLuiz Augusto von Dentz 	BT_DBG("result 0x%4.4x", rsp->result);
626115f02b91SLuiz Augusto von Dentz 
626215f02b91SLuiz Augusto von Dentz 	if (!result)
626315f02b91SLuiz Augusto von Dentz 		return 0;
626415f02b91SLuiz Augusto von Dentz 
626515f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
626615f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident)
626715f02b91SLuiz Augusto von Dentz 			continue;
626815f02b91SLuiz Augusto von Dentz 
626915f02b91SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
627015f02b91SLuiz Augusto von Dentz 	}
627115f02b91SLuiz Augusto von Dentz 
627215f02b91SLuiz Augusto von Dentz 	return 0;
627315f02b91SLuiz Augusto von Dentz }
627415f02b91SLuiz Augusto von Dentz 
627571fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
627671fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
627771fb4197SJohan Hedberg 				       u8 *data)
627871fb4197SJohan Hedberg {
627971fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
628071fb4197SJohan Hedberg 	struct l2cap_chan *chan;
628171fb4197SJohan Hedberg 
628271fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
628371fb4197SJohan Hedberg 		return -EPROTO;
628471fb4197SJohan Hedberg 
628571fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
628671fb4197SJohan Hedberg 
628771fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
628871fb4197SJohan Hedberg 	if (!chan)
628971fb4197SJohan Hedberg 		goto done;
629071fb4197SJohan Hedberg 
629171fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
629271fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
629371fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
629471fb4197SJohan Hedberg 
629571fb4197SJohan Hedberg done:
629671fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
629771fb4197SJohan Hedberg 	return 0;
629871fb4197SJohan Hedberg }
629971fb4197SJohan Hedberg 
63003300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
6301203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
6302203e639eSJohan Hedberg 				   u8 *data)
63033300d9a9SClaudio Takahasi {
6304b5ecba64SJohan Hedberg 	int err = 0;
6305b5ecba64SJohan Hedberg 
63063300d9a9SClaudio Takahasi 	switch (cmd->code) {
63073300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
630871fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
6309b5ecba64SJohan Hedberg 		break;
63103300d9a9SClaudio Takahasi 
63113300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
6312b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
6313b5ecba64SJohan Hedberg 		break;
63143300d9a9SClaudio Takahasi 
63153300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
6316b5ecba64SJohan Hedberg 		break;
63173300d9a9SClaudio Takahasi 
6318f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
6319f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
6320b5ecba64SJohan Hedberg 		break;
6321f1496deeSJohan Hedberg 
632227e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
6323b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
6324b5ecba64SJohan Hedberg 		break;
632527e2d4c8SJohan Hedberg 
6326fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
6327fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
6328fad5fc89SJohan Hedberg 		break;
6329fad5fc89SJohan Hedberg 
633015f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_REQ:
633115f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
633215f02b91SLuiz Augusto von Dentz 		break;
633315f02b91SLuiz Augusto von Dentz 
633415f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_RSP:
633515f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
633615f02b91SLuiz Augusto von Dentz 		break;
633715f02b91SLuiz Augusto von Dentz 
633815f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_REQ:
633915f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
634015f02b91SLuiz Augusto von Dentz 		break;
634115f02b91SLuiz Augusto von Dentz 
634215f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_RSP:
634315f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
634415f02b91SLuiz Augusto von Dentz 		break;
634515f02b91SLuiz Augusto von Dentz 
63463defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
6347b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
6348b5ecba64SJohan Hedberg 		break;
63493defe01aSJohan Hedberg 
63503defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
63513defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
6352b5ecba64SJohan Hedberg 		break;
63533defe01aSJohan Hedberg 
63543300d9a9SClaudio Takahasi 	default:
63553300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
6356b5ecba64SJohan Hedberg 		err = -EINVAL;
6357b5ecba64SJohan Hedberg 		break;
63583300d9a9SClaudio Takahasi 	}
6359b5ecba64SJohan Hedberg 
6360b5ecba64SJohan Hedberg 	return err;
63613300d9a9SClaudio Takahasi }
63623300d9a9SClaudio Takahasi 
6363c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
6364c5623556SJohan Hedberg 					struct sk_buff *skb)
6365c5623556SJohan Hedberg {
636669c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
63674f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
63684f3e219dSMarcel Holtmann 	u16 len;
6369c5623556SJohan Hedberg 	int err;
6370c5623556SJohan Hedberg 
637169c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
63723b166295SMarcel Holtmann 		goto drop;
637369c4e4e8SJohan Hedberg 
63744f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
63754f3e219dSMarcel Holtmann 		goto drop;
6376c5623556SJohan Hedberg 
63774f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
63784f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
6379c5623556SJohan Hedberg 
63804f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
6381c5623556SJohan Hedberg 
63824f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
63834f3e219dSMarcel Holtmann 
63844f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
6385c5623556SJohan Hedberg 		BT_DBG("corrupted command");
63864f3e219dSMarcel Holtmann 		goto drop;
6387c5623556SJohan Hedberg 	}
6388c5623556SJohan Hedberg 
6389203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
6390c5623556SJohan Hedberg 	if (err) {
6391c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
6392c5623556SJohan Hedberg 
6393c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
6394c5623556SJohan Hedberg 
6395dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
63964f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
6397c5623556SJohan Hedberg 			       sizeof(rej), &rej);
6398c5623556SJohan Hedberg 	}
6399c5623556SJohan Hedberg 
64003b166295SMarcel Holtmann drop:
6401c5623556SJohan Hedberg 	kfree_skb(skb);
6402c5623556SJohan Hedberg }
6403c5623556SJohan Hedberg 
64043300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
64053300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
64060a708f8fSGustavo F. Padovan {
640769c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
640855cee73eSLuiz Augusto von Dentz 	struct l2cap_cmd_hdr *cmd;
64093300d9a9SClaudio Takahasi 	int err;
64100a708f8fSGustavo F. Padovan 
64110a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
64120a708f8fSGustavo F. Padovan 
641369c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
64143b166295SMarcel Holtmann 		goto drop;
641569c4e4e8SJohan Hedberg 
641655cee73eSLuiz Augusto von Dentz 	while (skb->len >= L2CAP_CMD_HDR_SIZE) {
641755cee73eSLuiz Augusto von Dentz 		u16 len;
64180a708f8fSGustavo F. Padovan 
641955cee73eSLuiz Augusto von Dentz 		cmd = (void *) skb->data;
642055cee73eSLuiz Augusto von Dentz 		skb_pull(skb, L2CAP_CMD_HDR_SIZE);
64210a708f8fSGustavo F. Padovan 
642255cee73eSLuiz Augusto von Dentz 		len = le16_to_cpu(cmd->len);
64230a708f8fSGustavo F. Padovan 
642455cee73eSLuiz Augusto von Dentz 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
642555cee73eSLuiz Augusto von Dentz 		       cmd->ident);
642655cee73eSLuiz Augusto von Dentz 
642755cee73eSLuiz Augusto von Dentz 		if (len > skb->len || !cmd->ident) {
64280a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
64290a708f8fSGustavo F. Padovan 			break;
64300a708f8fSGustavo F. Padovan 		}
64310a708f8fSGustavo F. Padovan 
643255cee73eSLuiz Augusto von Dentz 		err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
64330a708f8fSGustavo F. Padovan 		if (err) {
6434e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
64352c6d1a2eSGustavo F. Padovan 
64362c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
64370a708f8fSGustavo F. Padovan 
6438dcf4adbfSJoe Perches 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
643955cee73eSLuiz Augusto von Dentz 			l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
64402d792818SGustavo Padovan 				       sizeof(rej), &rej);
64410a708f8fSGustavo F. Padovan 		}
64420a708f8fSGustavo F. Padovan 
644355cee73eSLuiz Augusto von Dentz 		skb_pull(skb, len);
64440a708f8fSGustavo F. Padovan 	}
64450a708f8fSGustavo F. Padovan 
64463b166295SMarcel Holtmann drop:
64470a708f8fSGustavo F. Padovan 	kfree_skb(skb);
64480a708f8fSGustavo F. Padovan }
64490a708f8fSGustavo F. Padovan 
645047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
64510a708f8fSGustavo F. Padovan {
64520a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
6453e4ca6d98SAndrei Emeltchenko 	int hdr_size;
6454e4ca6d98SAndrei Emeltchenko 
6455e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
6456e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
6457e4ca6d98SAndrei Emeltchenko 	else
6458e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
64590a708f8fSGustavo F. Padovan 
646047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
646103a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
64620a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
64630a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
64640a708f8fSGustavo F. Padovan 
64650a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
64660a708f8fSGustavo F. Padovan 			return -EBADMSG;
64670a708f8fSGustavo F. Padovan 	}
64680a708f8fSGustavo F. Padovan 	return 0;
64690a708f8fSGustavo F. Padovan }
64700a708f8fSGustavo F. Padovan 
64716ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
64720a708f8fSGustavo F. Padovan {
6473e31f7633SMat Martineau 	struct l2cap_ctrl control;
64740a708f8fSGustavo F. Padovan 
6475e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
64760a708f8fSGustavo F. Padovan 
6477e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
6478e31f7633SMat Martineau 	control.sframe = 1;
6479e31f7633SMat Martineau 	control.final = 1;
6480e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
6481e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
64820a708f8fSGustavo F. Padovan 
6483e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6484e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
6485e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
64860a708f8fSGustavo F. Padovan 	}
64870a708f8fSGustavo F. Padovan 
6488e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
6489e31f7633SMat Martineau 	    chan->unacked_frames > 0)
6490e31f7633SMat Martineau 		__set_retrans_timer(chan);
64910a708f8fSGustavo F. Padovan 
6492e31f7633SMat Martineau 	/* Send pending iframes */
6493525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
64940a708f8fSGustavo F. Padovan 
6495e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
6496e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
6497e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
6498e31f7633SMat Martineau 		 * send it now.
6499e31f7633SMat Martineau 		 */
6500e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
6501e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
65020a708f8fSGustavo F. Padovan 	}
65030a708f8fSGustavo F. Padovan }
65040a708f8fSGustavo F. Padovan 
65052d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
65062d792818SGustavo Padovan 			    struct sk_buff **last_frag)
65070a708f8fSGustavo F. Padovan {
650884084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
650984084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
651084084a31SMat Martineau 	 */
651184084a31SMat Martineau 	if (!skb_has_frag_list(skb))
651284084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
651384084a31SMat Martineau 
651484084a31SMat Martineau 	new_frag->next = NULL;
651584084a31SMat Martineau 
651684084a31SMat Martineau 	(*last_frag)->next = new_frag;
651784084a31SMat Martineau 	*last_frag = new_frag;
651884084a31SMat Martineau 
651984084a31SMat Martineau 	skb->len += new_frag->len;
652084084a31SMat Martineau 	skb->data_len += new_frag->len;
652184084a31SMat Martineau 	skb->truesize += new_frag->truesize;
652284084a31SMat Martineau }
652384084a31SMat Martineau 
65244b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
65254b51dae9SMat Martineau 				struct l2cap_ctrl *control)
652684084a31SMat Martineau {
652784084a31SMat Martineau 	int err = -EINVAL;
65280a708f8fSGustavo F. Padovan 
65294b51dae9SMat Martineau 	switch (control->sar) {
65307e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
653184084a31SMat Martineau 		if (chan->sdu)
653284084a31SMat Martineau 			break;
65330a708f8fSGustavo F. Padovan 
653480b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
653584084a31SMat Martineau 		break;
65360a708f8fSGustavo F. Padovan 
65377e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
653884084a31SMat Martineau 		if (chan->sdu)
653984084a31SMat Martineau 			break;
65400a708f8fSGustavo F. Padovan 
6541dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
6542dbb50887SDaniel Borkmann 			break;
6543dbb50887SDaniel Borkmann 
65446f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
654503a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
65460a708f8fSGustavo F. Padovan 
654784084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
654884084a31SMat Martineau 			err = -EMSGSIZE;
654984084a31SMat Martineau 			break;
655084084a31SMat Martineau 		}
65510a708f8fSGustavo F. Padovan 
655284084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
655384084a31SMat Martineau 			break;
655484084a31SMat Martineau 
655584084a31SMat Martineau 		chan->sdu = skb;
655684084a31SMat Martineau 		chan->sdu_last_frag = skb;
655784084a31SMat Martineau 
655884084a31SMat Martineau 		skb = NULL;
655984084a31SMat Martineau 		err = 0;
65600a708f8fSGustavo F. Padovan 		break;
65610a708f8fSGustavo F. Padovan 
65627e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
65636f61fd47SGustavo F. Padovan 		if (!chan->sdu)
656484084a31SMat Martineau 			break;
65650a708f8fSGustavo F. Padovan 
656684084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
656784084a31SMat Martineau 				&chan->sdu_last_frag);
656884084a31SMat Martineau 		skb = NULL;
65690a708f8fSGustavo F. Padovan 
657084084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
657184084a31SMat Martineau 			break;
65720a708f8fSGustavo F. Padovan 
657384084a31SMat Martineau 		err = 0;
65740a708f8fSGustavo F. Padovan 		break;
65750a708f8fSGustavo F. Padovan 
65767e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
65776f61fd47SGustavo F. Padovan 		if (!chan->sdu)
657884084a31SMat Martineau 			break;
65790a708f8fSGustavo F. Padovan 
658084084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
658184084a31SMat Martineau 				&chan->sdu_last_frag);
658284084a31SMat Martineau 		skb = NULL;
65830a708f8fSGustavo F. Padovan 
658484084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
658584084a31SMat Martineau 			break;
65860a708f8fSGustavo F. Padovan 
658780b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
65880a708f8fSGustavo F. Padovan 
658984084a31SMat Martineau 		if (!err) {
659084084a31SMat Martineau 			/* Reassembly complete */
659184084a31SMat Martineau 			chan->sdu = NULL;
659284084a31SMat Martineau 			chan->sdu_last_frag = NULL;
659384084a31SMat Martineau 			chan->sdu_len = 0;
65940a708f8fSGustavo F. Padovan 		}
65950a708f8fSGustavo F. Padovan 		break;
65960a708f8fSGustavo F. Padovan 	}
65970a708f8fSGustavo F. Padovan 
659884084a31SMat Martineau 	if (err) {
65990a708f8fSGustavo F. Padovan 		kfree_skb(skb);
66006f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
66016f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
660284084a31SMat Martineau 		chan->sdu_last_frag = NULL;
660384084a31SMat Martineau 		chan->sdu_len = 0;
660484084a31SMat Martineau 	}
66050a708f8fSGustavo F. Padovan 
660684084a31SMat Martineau 	return err;
66070a708f8fSGustavo F. Padovan }
66080a708f8fSGustavo F. Padovan 
660932b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
661032b32735SMat Martineau {
661132b32735SMat Martineau 	/* Placeholder */
661232b32735SMat Martineau 	return 0;
661332b32735SMat Martineau }
661432b32735SMat Martineau 
6615e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
66160a708f8fSGustavo F. Padovan {
661761aa4f5bSMat Martineau 	u8 event;
661861aa4f5bSMat Martineau 
661961aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
662061aa4f5bSMat Martineau 		return;
662161aa4f5bSMat Martineau 
662261aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6623401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
66240a708f8fSGustavo F. Padovan }
66250a708f8fSGustavo F. Padovan 
6626d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6627d2a7ac5dSMat Martineau {
662863838725SMat Martineau 	int err = 0;
662963838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
663063838725SMat Martineau 	 * until a gap is encountered.
663163838725SMat Martineau 	 */
663263838725SMat Martineau 
663363838725SMat Martineau 	BT_DBG("chan %p", chan);
663463838725SMat Martineau 
663563838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
663663838725SMat Martineau 		struct sk_buff *skb;
663763838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
663863838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
663963838725SMat Martineau 
664063838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
664163838725SMat Martineau 
664263838725SMat Martineau 		if (!skb)
664363838725SMat Martineau 			break;
664463838725SMat Martineau 
664563838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
664663838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
6647a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
664863838725SMat Martineau 		if (err)
664963838725SMat Martineau 			break;
665063838725SMat Martineau 	}
665163838725SMat Martineau 
665263838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
665363838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
665463838725SMat Martineau 		l2cap_send_ack(chan);
665563838725SMat Martineau 	}
665663838725SMat Martineau 
665763838725SMat Martineau 	return err;
6658d2a7ac5dSMat Martineau }
6659d2a7ac5dSMat Martineau 
6660d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6661d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6662d2a7ac5dSMat Martineau {
6663f80842a8SMat Martineau 	struct sk_buff *skb;
6664f80842a8SMat Martineau 
6665f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6666f80842a8SMat Martineau 
6667f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6668f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
66695e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6670f80842a8SMat Martineau 		return;
6671f80842a8SMat Martineau 	}
6672f80842a8SMat Martineau 
6673f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6674f80842a8SMat Martineau 
6675f80842a8SMat Martineau 	if (skb == NULL) {
6676f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6677f80842a8SMat Martineau 		       control->reqseq);
6678f80842a8SMat Martineau 		return;
6679f80842a8SMat Martineau 	}
6680f80842a8SMat Martineau 
6681a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6682f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
66835e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6684f80842a8SMat Martineau 		return;
6685f80842a8SMat Martineau 	}
6686f80842a8SMat Martineau 
6687f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6688f80842a8SMat Martineau 
6689f80842a8SMat Martineau 	if (control->poll) {
6690f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6691f80842a8SMat Martineau 
6692f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6693f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6694f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6695f80842a8SMat Martineau 
6696f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6697f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6698f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6699f80842a8SMat Martineau 		}
6700f80842a8SMat Martineau 	} else {
6701f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6702f80842a8SMat Martineau 
6703f80842a8SMat Martineau 		if (control->final) {
6704f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6705f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6706f80842a8SMat Martineau 						&chan->conn_state))
6707f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6708f80842a8SMat Martineau 		} else {
6709f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6710f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6711f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6712f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6713f80842a8SMat Martineau 			}
6714f80842a8SMat Martineau 		}
6715f80842a8SMat Martineau 	}
6716d2a7ac5dSMat Martineau }
6717d2a7ac5dSMat Martineau 
6718d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6719d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6720d2a7ac5dSMat Martineau {
6721fcd289dfSMat Martineau 	struct sk_buff *skb;
6722fcd289dfSMat Martineau 
6723fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6724fcd289dfSMat Martineau 
6725fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6726fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
67275e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6728fcd289dfSMat Martineau 		return;
6729fcd289dfSMat Martineau 	}
6730fcd289dfSMat Martineau 
6731fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6732fcd289dfSMat Martineau 
6733fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6734a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6735fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
67365e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6737fcd289dfSMat Martineau 		return;
6738fcd289dfSMat Martineau 	}
6739fcd289dfSMat Martineau 
6740fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6741fcd289dfSMat Martineau 
6742fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6743fcd289dfSMat Martineau 
6744fcd289dfSMat Martineau 	if (control->final) {
6745fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6746fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6747fcd289dfSMat Martineau 	} else {
6748fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6749fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6750fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6751fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6752fcd289dfSMat Martineau 	}
6753d2a7ac5dSMat Martineau }
6754d2a7ac5dSMat Martineau 
67554b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
67564b51dae9SMat Martineau {
67574b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
67584b51dae9SMat Martineau 
67594b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
67604b51dae9SMat Martineau 	       chan->expected_tx_seq);
67614b51dae9SMat Martineau 
67624b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
67634b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
67644b51dae9SMat Martineau 		    chan->tx_win) {
67654b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
67664b51dae9SMat Martineau 			 * invalid packets.
67674b51dae9SMat Martineau 			 */
67684b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
67694b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
67704b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
67714b51dae9SMat Martineau 			} else {
67724b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
67734b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
67744b51dae9SMat Martineau 			}
67754b51dae9SMat Martineau 		}
67764b51dae9SMat Martineau 
67774b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
67784b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
67794b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
67804b51dae9SMat Martineau 		}
67814b51dae9SMat Martineau 
67824b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
67834b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
67844b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
67854b51dae9SMat Martineau 		}
67864b51dae9SMat Martineau 
67874b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
67884b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
67894b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
67904b51dae9SMat Martineau 		}
67914b51dae9SMat Martineau 	}
67924b51dae9SMat Martineau 
67934b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
67944b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
67954b51dae9SMat Martineau 		    chan->tx_win) {
67964b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
67974b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
67984b51dae9SMat Martineau 		} else {
67994b51dae9SMat Martineau 			BT_DBG("Expected");
68004b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
68014b51dae9SMat Martineau 		}
68024b51dae9SMat Martineau 	}
68034b51dae9SMat Martineau 
68044b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
68052d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
68064b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
68074b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
68084b51dae9SMat Martineau 	}
68094b51dae9SMat Martineau 
68104b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
68114b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
68124b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
68134b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
68144b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
68154b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
68164b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
68174b51dae9SMat Martineau 		 * request.
68184b51dae9SMat Martineau 		 *
68194b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
68204b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
68214b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
68224b51dae9SMat Martineau 		 *
68234b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
68244b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
68254b51dae9SMat Martineau 		 * causes a disconnect.
68264b51dae9SMat Martineau 		 */
68274b51dae9SMat Martineau 
68284b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
68294b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
68304b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
68314b51dae9SMat Martineau 		} else {
68324b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
68334b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
68344b51dae9SMat Martineau 		}
68354b51dae9SMat Martineau 	} else {
68364b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
68374b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
68384b51dae9SMat Martineau 	}
68394b51dae9SMat Martineau }
68404b51dae9SMat Martineau 
6841d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6842d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6843d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6844d2a7ac5dSMat Martineau {
6845d2a7ac5dSMat Martineau 	int err = 0;
6846941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6847d2a7ac5dSMat Martineau 
6848d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6849d2a7ac5dSMat Martineau 	       event);
6850d2a7ac5dSMat Martineau 
6851d2a7ac5dSMat Martineau 	switch (event) {
6852d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6853d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6854d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6855d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6856d2a7ac5dSMat Martineau 
6857d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6858d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6859d2a7ac5dSMat Martineau 				       control->txseq);
6860d2a7ac5dSMat Martineau 				break;
6861d2a7ac5dSMat Martineau 			}
6862d2a7ac5dSMat Martineau 
6863d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6864d2a7ac5dSMat Martineau 							   control->txseq);
6865d2a7ac5dSMat Martineau 
6866d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6867941247f9SPeter Senna Tschudin 			skb_in_use = true;
6868d2a7ac5dSMat Martineau 
6869d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6870d2a7ac5dSMat Martineau 			if (err)
6871d2a7ac5dSMat Martineau 				break;
6872d2a7ac5dSMat Martineau 
6873d2a7ac5dSMat Martineau 			if (control->final) {
6874d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6875d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6876d2a7ac5dSMat Martineau 					control->final = 0;
6877d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6878d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6879d2a7ac5dSMat Martineau 				}
6880d2a7ac5dSMat Martineau 			}
6881d2a7ac5dSMat Martineau 
6882d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6883d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6884d2a7ac5dSMat Martineau 			break;
6885d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6886d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6887d2a7ac5dSMat Martineau 
6888d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6889d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6890d2a7ac5dSMat Martineau 			 * when local busy is exited.
6891d2a7ac5dSMat Martineau 			 */
6892d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6893d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6894d2a7ac5dSMat Martineau 				       control->txseq);
6895d2a7ac5dSMat Martineau 				break;
6896d2a7ac5dSMat Martineau 			}
6897d2a7ac5dSMat Martineau 
6898d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6899d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6900d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6901d2a7ac5dSMat Martineau 			 */
6902d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6903941247f9SPeter Senna Tschudin 			skb_in_use = true;
6904d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6905d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6906d2a7ac5dSMat Martineau 
6907d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6908d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6909d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6910d2a7ac5dSMat Martineau 
6911d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6912d2a7ac5dSMat Martineau 			break;
6913d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6914d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6915d2a7ac5dSMat Martineau 			break;
6916d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6917d2a7ac5dSMat Martineau 			break;
6918d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6919d2a7ac5dSMat Martineau 		default:
69205e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6921d2a7ac5dSMat Martineau 			break;
6922d2a7ac5dSMat Martineau 		}
6923d2a7ac5dSMat Martineau 		break;
6924d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6925d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6926d2a7ac5dSMat Martineau 		if (control->final) {
6927d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6928d2a7ac5dSMat Martineau 
6929e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6930e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6931d2a7ac5dSMat Martineau 				control->final = 0;
6932d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6933d2a7ac5dSMat Martineau 			}
6934d2a7ac5dSMat Martineau 
6935d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6936d2a7ac5dSMat Martineau 		} else if (control->poll) {
6937d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6938d2a7ac5dSMat Martineau 		} else {
6939d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6940d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6941d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6942d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6943d2a7ac5dSMat Martineau 
6944d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6945d2a7ac5dSMat Martineau 		}
6946d2a7ac5dSMat Martineau 		break;
6947d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6948d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6949d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6950d2a7ac5dSMat Martineau 		if (control && control->poll) {
6951d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6952d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6953d2a7ac5dSMat Martineau 		}
6954d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6955d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6956d2a7ac5dSMat Martineau 		break;
6957d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6958d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6959d2a7ac5dSMat Martineau 		break;
6960d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6961d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6962d2a7ac5dSMat Martineau 		break;
6963d2a7ac5dSMat Martineau 	default:
6964d2a7ac5dSMat Martineau 		break;
6965d2a7ac5dSMat Martineau 	}
6966d2a7ac5dSMat Martineau 
6967d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6968d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6969d2a7ac5dSMat Martineau 		kfree_skb(skb);
6970d2a7ac5dSMat Martineau 	}
6971d2a7ac5dSMat Martineau 
6972d2a7ac5dSMat Martineau 	return err;
6973d2a7ac5dSMat Martineau }
6974d2a7ac5dSMat Martineau 
6975d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6976d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6977d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6978d2a7ac5dSMat Martineau {
6979d2a7ac5dSMat Martineau 	int err = 0;
6980d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6981941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6982d2a7ac5dSMat Martineau 
6983d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6984d2a7ac5dSMat Martineau 	       event);
6985d2a7ac5dSMat Martineau 
6986d2a7ac5dSMat Martineau 	switch (event) {
6987d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6988d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6989d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6990d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6991d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6992d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6993941247f9SPeter Senna Tschudin 			skb_in_use = true;
6994d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6995d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6996d2a7ac5dSMat Martineau 
6997d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6998d2a7ac5dSMat Martineau 			break;
6999d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
7000d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
7001d2a7ac5dSMat Martineau 
7002d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7003d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7004941247f9SPeter Senna Tschudin 			skb_in_use = true;
7005d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7006d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7007d2a7ac5dSMat Martineau 
7008d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
7009d2a7ac5dSMat Martineau 			if (err)
7010d2a7ac5dSMat Martineau 				break;
7011d2a7ac5dSMat Martineau 
7012d2a7ac5dSMat Martineau 			break;
7013d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
7014d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
7015d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
7016d2a7ac5dSMat Martineau 			 * the missing frames.
7017d2a7ac5dSMat Martineau 			 */
7018d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7019941247f9SPeter Senna Tschudin 			skb_in_use = true;
7020d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7021d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7022d2a7ac5dSMat Martineau 
7023d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7024d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
7025d2a7ac5dSMat Martineau 			break;
7026d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
7027d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
7028d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
7029d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
7030d2a7ac5dSMat Martineau 			 * SREJ'd frames.
7031d2a7ac5dSMat Martineau 			 */
7032d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7033941247f9SPeter Senna Tschudin 			skb_in_use = true;
7034d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7035d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7036d2a7ac5dSMat Martineau 
7037d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7038d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
7039d2a7ac5dSMat Martineau 			break;
7040d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
7041d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
7042d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7043d2a7ac5dSMat Martineau 			break;
7044d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
7045d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
7046d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
7047d2a7ac5dSMat Martineau 			 */
7048d2a7ac5dSMat Martineau 			break;
7049d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
7050d2a7ac5dSMat Martineau 			break;
7051d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
7052d2a7ac5dSMat Martineau 		default:
70535e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7054d2a7ac5dSMat Martineau 			break;
7055d2a7ac5dSMat Martineau 		}
7056d2a7ac5dSMat Martineau 		break;
7057d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
7058d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7059d2a7ac5dSMat Martineau 		if (control->final) {
7060d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7061d2a7ac5dSMat Martineau 
7062d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
7063d2a7ac5dSMat Martineau 						&chan->conn_state)) {
7064d2a7ac5dSMat Martineau 				control->final = 0;
7065d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
7066d2a7ac5dSMat Martineau 			}
7067d2a7ac5dSMat Martineau 
7068d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
7069d2a7ac5dSMat Martineau 		} else if (control->poll) {
7070d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7071d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7072d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
7073d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7074d2a7ac5dSMat Martineau 			}
7075d2a7ac5dSMat Martineau 
7076d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
7077d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7078d2a7ac5dSMat Martineau 		} else {
7079d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7080d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7081d2a7ac5dSMat Martineau 			    chan->unacked_frames)
7082d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7083d2a7ac5dSMat Martineau 
7084d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
7085d2a7ac5dSMat Martineau 		}
7086d2a7ac5dSMat Martineau 		break;
7087d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
7088d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7089d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7090d2a7ac5dSMat Martineau 		if (control->poll) {
7091d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7092d2a7ac5dSMat Martineau 		} else {
7093d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
7094d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
7095d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
7096d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
7097d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
7098d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
7099d2a7ac5dSMat Martineau 		}
7100d2a7ac5dSMat Martineau 
7101d2a7ac5dSMat Martineau 		break;
7102d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
7103d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
7104d2a7ac5dSMat Martineau 		break;
7105d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
7106d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
7107d2a7ac5dSMat Martineau 		break;
7108d2a7ac5dSMat Martineau 	}
7109d2a7ac5dSMat Martineau 
7110d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
7111d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
7112d2a7ac5dSMat Martineau 		kfree_skb(skb);
7113d2a7ac5dSMat Martineau 	}
7114d2a7ac5dSMat Martineau 
7115d2a7ac5dSMat Martineau 	return err;
7116d2a7ac5dSMat Martineau }
7117d2a7ac5dSMat Martineau 
711832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
711932b32735SMat Martineau {
712032b32735SMat Martineau 	BT_DBG("chan %p", chan);
712132b32735SMat Martineau 
712232b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
712332b32735SMat Martineau 
712432b32735SMat Martineau 	if (chan->hs_hcon)
712532b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
712632b32735SMat Martineau 	else
712732b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
712832b32735SMat Martineau 
712932b32735SMat Martineau 	return l2cap_resegment(chan);
713032b32735SMat Martineau }
713132b32735SMat Martineau 
713232b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
713332b32735SMat Martineau 				 struct l2cap_ctrl *control,
713432b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
713532b32735SMat Martineau {
713632b32735SMat Martineau 	int err;
713732b32735SMat Martineau 
713832b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
713932b32735SMat Martineau 	       event);
714032b32735SMat Martineau 
714132b32735SMat Martineau 	if (!control->poll)
714232b32735SMat Martineau 		return -EPROTO;
714332b32735SMat Martineau 
714432b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
714532b32735SMat Martineau 
714632b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
714732b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
714832b32735SMat Martineau 	else
714932b32735SMat Martineau 		chan->tx_send_head = NULL;
715032b32735SMat Martineau 
715132b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
715232b32735SMat Martineau 	 * by the receiver.
715332b32735SMat Martineau 	 */
715432b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
715532b32735SMat Martineau 	chan->unacked_frames = 0;
715632b32735SMat Martineau 
715732b32735SMat Martineau 	err = l2cap_finish_move(chan);
715832b32735SMat Martineau 	if (err)
715932b32735SMat Martineau 		return err;
716032b32735SMat Martineau 
716132b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
716232b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
716332b32735SMat Martineau 
716432b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
716532b32735SMat Martineau 		return -EPROTO;
716632b32735SMat Martineau 
716732b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
716832b32735SMat Martineau }
716932b32735SMat Martineau 
717032b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
717132b32735SMat Martineau 				 struct l2cap_ctrl *control,
717232b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
717332b32735SMat Martineau {
717432b32735SMat Martineau 	int err;
717532b32735SMat Martineau 
717632b32735SMat Martineau 	if (!control->final)
717732b32735SMat Martineau 		return -EPROTO;
717832b32735SMat Martineau 
717932b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
718032b32735SMat Martineau 
718132b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
718232b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
718332b32735SMat Martineau 
718432b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
718532b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
718632b32735SMat Martineau 	else
718732b32735SMat Martineau 		chan->tx_send_head = NULL;
718832b32735SMat Martineau 
718932b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
719032b32735SMat Martineau 	 * by the receiver.
719132b32735SMat Martineau 	 */
719232b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
719332b32735SMat Martineau 	chan->unacked_frames = 0;
719432b32735SMat Martineau 
719532b32735SMat Martineau 	if (chan->hs_hcon)
719632b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
719732b32735SMat Martineau 	else
719832b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
719932b32735SMat Martineau 
720032b32735SMat Martineau 	err = l2cap_resegment(chan);
720132b32735SMat Martineau 
720232b32735SMat Martineau 	if (!err)
720332b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
720432b32735SMat Martineau 
720532b32735SMat Martineau 	return err;
720632b32735SMat Martineau }
720732b32735SMat Martineau 
7208d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
7209d2a7ac5dSMat Martineau {
7210d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
7211d2a7ac5dSMat Martineau 	u16 unacked;
7212d2a7ac5dSMat Martineau 
7213d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
7214d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
7215d2a7ac5dSMat Martineau }
7216d2a7ac5dSMat Martineau 
7217cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7218cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
72190a708f8fSGustavo F. Padovan {
7220d2a7ac5dSMat Martineau 	int err = 0;
7221d2a7ac5dSMat Martineau 
7222d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
7223d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
7224d2a7ac5dSMat Martineau 
7225d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
7226d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
7227d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
7228d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
7229d2a7ac5dSMat Martineau 			break;
7230d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
7231d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
7232d2a7ac5dSMat Martineau 						       event);
7233d2a7ac5dSMat Martineau 			break;
723432b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
723532b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
723632b32735SMat Martineau 			break;
723732b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
723832b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
723932b32735SMat Martineau 			break;
7240d2a7ac5dSMat Martineau 		default:
7241d2a7ac5dSMat Martineau 			/* shut it down */
7242d2a7ac5dSMat Martineau 			break;
7243d2a7ac5dSMat Martineau 		}
7244d2a7ac5dSMat Martineau 	} else {
7245d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
7246d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
7247d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
72485e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
7249d2a7ac5dSMat Martineau 	}
7250d2a7ac5dSMat Martineau 
7251d2a7ac5dSMat Martineau 	return err;
7252cec8ab6eSMat Martineau }
7253cec8ab6eSMat Martineau 
7254cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7255cec8ab6eSMat Martineau 			   struct sk_buff *skb)
7256cec8ab6eSMat Martineau {
72574b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
72584b51dae9SMat Martineau 	       chan->rx_state);
72594b51dae9SMat Martineau 
72604b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
72614b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
72624b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
72634b51dae9SMat Martineau 
72644b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
72654b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
72664b51dae9SMat Martineau 
72674b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
72684b51dae9SMat Martineau 
72694b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
72704b51dae9SMat Martineau 	} else {
72714b51dae9SMat Martineau 		if (chan->sdu) {
72724b51dae9SMat Martineau 			kfree_skb(chan->sdu);
72734b51dae9SMat Martineau 			chan->sdu = NULL;
72744b51dae9SMat Martineau 		}
72754b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
72764b51dae9SMat Martineau 		chan->sdu_len = 0;
72774b51dae9SMat Martineau 
72784b51dae9SMat Martineau 		if (skb) {
72794b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
72804b51dae9SMat Martineau 			kfree_skb(skb);
72814b51dae9SMat Martineau 		}
72824b51dae9SMat Martineau 	}
72834b51dae9SMat Martineau 
72844b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
72854b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
72864b51dae9SMat Martineau 
72879a544210SPrasanna Karthik 	return 0;
7288cec8ab6eSMat Martineau }
7289cec8ab6eSMat Martineau 
7290cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7291cec8ab6eSMat Martineau {
7292a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
7293cec8ab6eSMat Martineau 	u16 len;
7294cec8ab6eSMat Martineau 	u8 event;
72950a708f8fSGustavo F. Padovan 
7296b76bbd66SMat Martineau 	__unpack_control(chan, skb);
7297b76bbd66SMat Martineau 
72980a708f8fSGustavo F. Padovan 	len = skb->len;
72990a708f8fSGustavo F. Padovan 
73000a708f8fSGustavo F. Padovan 	/*
73010a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
73020a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
7303cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
73040a708f8fSGustavo F. Padovan 	 */
730547d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
73060a708f8fSGustavo F. Padovan 		goto drop;
73070a708f8fSGustavo F. Padovan 
7308cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
730903a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
73100a708f8fSGustavo F. Padovan 
731147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
731203a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
73130a708f8fSGustavo F. Padovan 
731447d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
73155e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
73160a708f8fSGustavo F. Padovan 		goto drop;
73170a708f8fSGustavo F. Padovan 	}
73180a708f8fSGustavo F. Padovan 
7319f1942564SLuiz Augusto von Dentz 	if (chan->ops->filter) {
7320f1942564SLuiz Augusto von Dentz 		if (chan->ops->filter(chan, skb))
7321dbb50887SDaniel Borkmann 			goto drop;
7322f1942564SLuiz Augusto von Dentz 	}
7323dbb50887SDaniel Borkmann 
7324cec8ab6eSMat Martineau 	if (!control->sframe) {
7325cec8ab6eSMat Martineau 		int err;
73260a708f8fSGustavo F. Padovan 
7327cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
7328cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
7329cec8ab6eSMat Martineau 		       control->txseq);
7330836be934SAndrei Emeltchenko 
7331cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
7332cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
7333cec8ab6eSMat Martineau 		 */
7334cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
73350a708f8fSGustavo F. Padovan 			goto drop;
73360a708f8fSGustavo F. Padovan 
7337cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
7338cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
7339cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
73400a708f8fSGustavo F. Padovan 		} else {
7341cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
7342cec8ab6eSMat Martineau 		}
7343cec8ab6eSMat Martineau 
7344cec8ab6eSMat Martineau 		if (err)
73455e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7346cec8ab6eSMat Martineau 	} else {
7347cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
7348cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
7349cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
7350cec8ab6eSMat Martineau 		};
7351cec8ab6eSMat Martineau 
7352cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
7353cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
7354cec8ab6eSMat Martineau 			goto drop;
7355cec8ab6eSMat Martineau 
7356cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
7357cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
7358cec8ab6eSMat Martineau 		       control->super);
7359cec8ab6eSMat Martineau 
73600a708f8fSGustavo F. Padovan 		if (len != 0) {
73611bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
73625e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
73630a708f8fSGustavo F. Padovan 			goto drop;
73640a708f8fSGustavo F. Padovan 		}
73650a708f8fSGustavo F. Padovan 
7366cec8ab6eSMat Martineau 		/* Validate F and P bits */
7367cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
7368cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
7369cec8ab6eSMat Martineau 			goto drop;
7370cec8ab6eSMat Martineau 
7371cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
7372cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
73735e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
73740a708f8fSGustavo F. Padovan 	}
73750a708f8fSGustavo F. Padovan 
73760a708f8fSGustavo F. Padovan 	return 0;
73770a708f8fSGustavo F. Padovan 
73780a708f8fSGustavo F. Padovan drop:
73790a708f8fSGustavo F. Padovan 	kfree_skb(skb);
73800a708f8fSGustavo F. Padovan 	return 0;
73810a708f8fSGustavo F. Padovan }
73820a708f8fSGustavo F. Padovan 
7383b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
7384b1c325c2SJohan Hedberg {
7385b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
7386b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
7387b1c325c2SJohan Hedberg 	u16 return_credits;
7388b1c325c2SJohan Hedberg 
738915f02b91SLuiz Augusto von Dentz 	return_credits = (chan->imtu / chan->mps) + 1;
7390b1c325c2SJohan Hedberg 
739115f02b91SLuiz Augusto von Dentz 	if (chan->rx_credits >= return_credits)
739296cd8eaaSLuiz Augusto von Dentz 		return;
7393b1c325c2SJohan Hedberg 
739415f02b91SLuiz Augusto von Dentz 	return_credits -= chan->rx_credits;
739515f02b91SLuiz Augusto von Dentz 
7396b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
7397b1c325c2SJohan Hedberg 
7398b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
7399b1c325c2SJohan Hedberg 
7400b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
7401b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
7402b1c325c2SJohan Hedberg 
7403b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
7404b1c325c2SJohan Hedberg 
7405b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
7406b1c325c2SJohan Hedberg }
7407b1c325c2SJohan Hedberg 
740815f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
740996cd8eaaSLuiz Augusto von Dentz {
741096cd8eaaSLuiz Augusto von Dentz 	int err;
741196cd8eaaSLuiz Augusto von Dentz 
741296cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
741396cd8eaaSLuiz Augusto von Dentz 
741496cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
741596cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
741696cd8eaaSLuiz Augusto von Dentz 
741796cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
741896cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
741996cd8eaaSLuiz Augusto von Dentz 
742096cd8eaaSLuiz Augusto von Dentz 	return err;
742196cd8eaaSLuiz Augusto von Dentz }
742296cd8eaaSLuiz Augusto von Dentz 
742315f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7424fad5fc89SJohan Hedberg {
7425aac23bf6SJohan Hedberg 	int err;
7426fad5fc89SJohan Hedberg 
7427aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
7428aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
7429dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
7430fad5fc89SJohan Hedberg 		return -ENOBUFS;
7431aac23bf6SJohan Hedberg 	}
7432aac23bf6SJohan Hedberg 
7433aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
7434aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
7435aac23bf6SJohan Hedberg 		return -ENOBUFS;
7436aac23bf6SJohan Hedberg 	}
7437fad5fc89SJohan Hedberg 
7438fad5fc89SJohan Hedberg 	chan->rx_credits--;
7439fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
7440fad5fc89SJohan Hedberg 
744196cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
744296cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
744396cd8eaaSLuiz Augusto von Dentz 	 */
744496cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
7445fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
7446fad5fc89SJohan Hedberg 
7447aac23bf6SJohan Hedberg 	err = 0;
7448aac23bf6SJohan Hedberg 
7449aac23bf6SJohan Hedberg 	if (!chan->sdu) {
7450aac23bf6SJohan Hedberg 		u16 sdu_len;
7451aac23bf6SJohan Hedberg 
7452aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
7453aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
7454aac23bf6SJohan Hedberg 
7455aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
7456aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
7457aac23bf6SJohan Hedberg 
7458aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
7459aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
7460aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
7461aac23bf6SJohan Hedberg 			goto failed;
7462aac23bf6SJohan Hedberg 		}
7463aac23bf6SJohan Hedberg 
7464aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
7465aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
7466aac23bf6SJohan Hedberg 			err = -EINVAL;
7467aac23bf6SJohan Hedberg 			goto failed;
7468aac23bf6SJohan Hedberg 		}
7469aac23bf6SJohan Hedberg 
7470aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
747115f02b91SLuiz Augusto von Dentz 			return l2cap_ecred_recv(chan, skb);
7472aac23bf6SJohan Hedberg 
7473aac23bf6SJohan Hedberg 		chan->sdu = skb;
7474aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
7475aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
7476aac23bf6SJohan Hedberg 
7477a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
7478a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
7479a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
7480a5c3021bSLuiz Augusto von Dentz 
7481a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
7482a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
7483a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
7484a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
7485a5c3021bSLuiz Augusto von Dentz 		}
7486a5c3021bSLuiz Augusto von Dentz 
7487aac23bf6SJohan Hedberg 		return 0;
7488aac23bf6SJohan Hedberg 	}
7489aac23bf6SJohan Hedberg 
7490aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
7491aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
7492aac23bf6SJohan Hedberg 
7493aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
7494aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
7495aac23bf6SJohan Hedberg 		err = -EINVAL;
7496aac23bf6SJohan Hedberg 		goto failed;
7497aac23bf6SJohan Hedberg 	}
7498aac23bf6SJohan Hedberg 
7499aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
7500aac23bf6SJohan Hedberg 	skb = NULL;
7501aac23bf6SJohan Hedberg 
7502aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
750315f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_recv(chan, chan->sdu);
7504aac23bf6SJohan Hedberg 		if (!err) {
7505aac23bf6SJohan Hedberg 			chan->sdu = NULL;
7506aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
7507aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
7508aac23bf6SJohan Hedberg 		}
7509aac23bf6SJohan Hedberg 	}
7510aac23bf6SJohan Hedberg 
7511aac23bf6SJohan Hedberg failed:
7512aac23bf6SJohan Hedberg 	if (err) {
7513aac23bf6SJohan Hedberg 		kfree_skb(skb);
7514aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
7515aac23bf6SJohan Hedberg 		chan->sdu = NULL;
7516aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
7517aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
7518aac23bf6SJohan Hedberg 	}
7519aac23bf6SJohan Hedberg 
7520aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
7521aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
7522aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
7523aac23bf6SJohan Hedberg 	 */
7524aac23bf6SJohan Hedberg 	return 0;
7525fad5fc89SJohan Hedberg }
7526fad5fc89SJohan Hedberg 
752713ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
752813ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
75290a708f8fSGustavo F. Padovan {
753048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
75310a708f8fSGustavo F. Padovan 
7532baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
753348454079SGustavo F. Padovan 	if (!chan) {
753497e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
753597e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
753697e8e89dSAndrei Emeltchenko 			if (!chan) {
753797e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
753813ca56e0SAndrei Emeltchenko 				return;
753997e8e89dSAndrei Emeltchenko 			}
754097e8e89dSAndrei Emeltchenko 
754197e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
754297e8e89dSAndrei Emeltchenko 		} else {
75430a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
75446be36555SAndrei Emeltchenko 			/* Drop packet and return */
75453379013bSDan Carpenter 			kfree_skb(skb);
754613ca56e0SAndrei Emeltchenko 			return;
75470a708f8fSGustavo F. Padovan 		}
754897e8e89dSAndrei Emeltchenko 	}
75490a708f8fSGustavo F. Padovan 
755049208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
75510a708f8fSGustavo F. Padovan 
7552315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
7553315917e0SJohan Hedberg 	 * procdure is done simply assume that the channel is supported
7554315917e0SJohan Hedberg 	 * and mark it as ready.
7555315917e0SJohan Hedberg 	 */
7556315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
7557315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
7558315917e0SJohan Hedberg 
755989bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
75600a708f8fSGustavo F. Padovan 		goto drop;
75610a708f8fSGustavo F. Padovan 
75620c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
756338319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
756415f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
756515f02b91SLuiz Augusto von Dentz 		if (l2cap_ecred_data_rcv(chan, skb) < 0)
7566fad5fc89SJohan Hedberg 			goto drop;
7567fad5fc89SJohan Hedberg 
7568fad5fc89SJohan Hedberg 		goto done;
7569fad5fc89SJohan Hedberg 
75700a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
75710a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
75720a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
75730a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
75740a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
75750a708f8fSGustavo F. Padovan 
75762c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
75772c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
75780a708f8fSGustavo F. Padovan 			goto drop;
75792c96e03dSSzymon Janc 		}
75800a708f8fSGustavo F. Padovan 
758180b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
75820a708f8fSGustavo F. Padovan 			goto done;
75830a708f8fSGustavo F. Padovan 		break;
75840a708f8fSGustavo F. Padovan 
75850a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
75860a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
7587cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
75880a708f8fSGustavo F. Padovan 		goto done;
75890a708f8fSGustavo F. Padovan 
75900a708f8fSGustavo F. Padovan 	default:
75910c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
75920a708f8fSGustavo F. Padovan 		break;
75930a708f8fSGustavo F. Padovan 	}
75940a708f8fSGustavo F. Padovan 
75950a708f8fSGustavo F. Padovan drop:
75960a708f8fSGustavo F. Padovan 	kfree_skb(skb);
75970a708f8fSGustavo F. Padovan 
75980a708f8fSGustavo F. Padovan done:
75996be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
76000a708f8fSGustavo F. Padovan }
76010a708f8fSGustavo F. Padovan 
760284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
760384104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
76040a708f8fSGustavo F. Padovan {
7605ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
760623691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
76070a708f8fSGustavo F. Padovan 
7608ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
7609a24cce14SJohan Hedberg 		goto free_skb;
7610ae4fd2d3SMarcel Holtmann 
7611bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
7612bf20fd4eSJohan Hedberg 					ACL_LINK);
761323691d75SGustavo F. Padovan 	if (!chan)
7614a24cce14SJohan Hedberg 		goto free_skb;
76150a708f8fSGustavo F. Padovan 
76165b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
76170a708f8fSGustavo F. Padovan 
761889bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
76190a708f8fSGustavo F. Padovan 		goto drop;
76200a708f8fSGustavo F. Padovan 
7621e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
76220a708f8fSGustavo F. Padovan 		goto drop;
76230a708f8fSGustavo F. Padovan 
76242edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
7625a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
7626a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
76272edf870dSMarcel Holtmann 
7628a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
7629a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
763084104b24SAndrei Emeltchenko 		return;
7631a24cce14SJohan Hedberg 	}
76320a708f8fSGustavo F. Padovan 
76330a708f8fSGustavo F. Padovan drop:
7634a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
7635a24cce14SJohan Hedberg free_skb:
76360a708f8fSGustavo F. Padovan 	kfree_skb(skb);
76370a708f8fSGustavo F. Padovan }
76380a708f8fSGustavo F. Padovan 
76390a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
76400a708f8fSGustavo F. Padovan {
76410a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
764261a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
76430a708f8fSGustavo F. Padovan 	u16 cid, len;
76440a708f8fSGustavo F. Padovan 	__le16 psm;
76450a708f8fSGustavo F. Padovan 
764661a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
764761a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
764861a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
764961a939c6SJohan Hedberg 		return;
765061a939c6SJohan Hedberg 	}
765161a939c6SJohan Hedberg 
76520a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
76530a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
76540a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
76550a708f8fSGustavo F. Padovan 
76560a708f8fSGustavo F. Padovan 	if (len != skb->len) {
76570a708f8fSGustavo F. Padovan 		kfree_skb(skb);
76580a708f8fSGustavo F. Padovan 		return;
76590a708f8fSGustavo F. Padovan 	}
76600a708f8fSGustavo F. Padovan 
76619e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
76629e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
76639e1d7e15SJohan Hedberg 	 */
76649e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
7665dcc36c16SJohan Hedberg 	    hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
7666a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
7667e493150eSJohan Hedberg 		kfree_skb(skb);
7668e493150eSJohan Hedberg 		return;
7669e493150eSJohan Hedberg 	}
7670e493150eSJohan Hedberg 
76710a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
76720a708f8fSGustavo F. Padovan 
76730a708f8fSGustavo F. Padovan 	switch (cid) {
76740a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
76750a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
76760a708f8fSGustavo F. Padovan 		break;
76770a708f8fSGustavo F. Padovan 
76780a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7679097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
76800181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
76810a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
76820a708f8fSGustavo F. Padovan 		break;
76830a708f8fSGustavo F. Padovan 
7684a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7685a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7686a2877629SMarcel Holtmann 		break;
7687a2877629SMarcel Holtmann 
76880a708f8fSGustavo F. Padovan 	default:
76890a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
76900a708f8fSGustavo F. Padovan 		break;
76910a708f8fSGustavo F. Padovan 	}
76920a708f8fSGustavo F. Padovan }
76930a708f8fSGustavo F. Padovan 
769461a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
769561a939c6SJohan Hedberg {
769661a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
769761a939c6SJohan Hedberg 					       pending_rx_work);
769861a939c6SJohan Hedberg 	struct sk_buff *skb;
769961a939c6SJohan Hedberg 
770061a939c6SJohan Hedberg 	BT_DBG("");
770161a939c6SJohan Hedberg 
770261a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
770361a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
770461a939c6SJohan Hedberg }
770561a939c6SJohan Hedberg 
7706162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
7707162b49e7SJohan Hedberg {
7708162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
7709162b49e7SJohan Hedberg 	struct hci_chan *hchan;
7710162b49e7SJohan Hedberg 
7711162b49e7SJohan Hedberg 	if (conn)
7712162b49e7SJohan Hedberg 		return conn;
7713162b49e7SJohan Hedberg 
7714162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
7715162b49e7SJohan Hedberg 	if (!hchan)
7716162b49e7SJohan Hedberg 		return NULL;
7717162b49e7SJohan Hedberg 
771827f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
7719162b49e7SJohan Hedberg 	if (!conn) {
7720162b49e7SJohan Hedberg 		hci_chan_del(hchan);
7721162b49e7SJohan Hedberg 		return NULL;
7722162b49e7SJohan Hedberg 	}
7723162b49e7SJohan Hedberg 
7724162b49e7SJohan Hedberg 	kref_init(&conn->ref);
7725162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
772651bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
7727162b49e7SJohan Hedberg 	conn->hchan = hchan;
7728162b49e7SJohan Hedberg 
7729162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
7730162b49e7SJohan Hedberg 
7731162b49e7SJohan Hedberg 	switch (hcon->type) {
7732162b49e7SJohan Hedberg 	case LE_LINK:
7733162b49e7SJohan Hedberg 		if (hcon->hdev->le_mtu) {
7734162b49e7SJohan Hedberg 			conn->mtu = hcon->hdev->le_mtu;
7735162b49e7SJohan Hedberg 			break;
7736162b49e7SJohan Hedberg 		}
773719186c7bSGustavo A. R. Silva 		fallthrough;
7738162b49e7SJohan Hedberg 	default:
7739162b49e7SJohan Hedberg 		conn->mtu = hcon->hdev->acl_mtu;
7740162b49e7SJohan Hedberg 		break;
7741162b49e7SJohan Hedberg 	}
7742162b49e7SJohan Hedberg 
7743162b49e7SJohan Hedberg 	conn->feat_mask = 0;
7744162b49e7SJohan Hedberg 
77450bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
77460bd49fc7SJohan Hedberg 
77470bd49fc7SJohan Hedberg 	if (hcon->type == ACL_LINK &&
7748d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
77490bd49fc7SJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_A2MP;
7750162b49e7SJohan Hedberg 
7751d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
7752f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
7753b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
7754b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
7755b5ae344dSJohan Hedberg 
77565a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
7757162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
7758162b49e7SJohan Hedberg 
7759162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
7760162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
7761162b49e7SJohan Hedberg 
7762162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
7763162b49e7SJohan Hedberg 
776461a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
776561a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
7766f3d82d0cSJohan Hedberg 	INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr);
776761a939c6SJohan Hedberg 
7768162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
7769162b49e7SJohan Hedberg 
7770162b49e7SJohan Hedberg 	return conn;
7771162b49e7SJohan Hedberg }
7772162b49e7SJohan Hedberg 
7773162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) {
7774162b49e7SJohan Hedberg 	if (!psm)
7775162b49e7SJohan Hedberg 		return false;
7776162b49e7SJohan Hedberg 
7777162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
7778162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
7779162b49e7SJohan Hedberg 
7780162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
7781162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
7782162b49e7SJohan Hedberg }
7783162b49e7SJohan Hedberg 
7784da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
7785da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
7786da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7787da49b602SLuiz Augusto von Dentz 	int count;
7788da49b602SLuiz Augusto von Dentz };
7789da49b602SLuiz Augusto von Dentz 
7790da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
7791da49b602SLuiz Augusto von Dentz {
7792da49b602SLuiz Augusto von Dentz 	struct l2cap_chan_data *d = data;
7793da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7794da49b602SLuiz Augusto von Dentz 
7795da49b602SLuiz Augusto von Dentz 	if (chan == d->chan)
7796da49b602SLuiz Augusto von Dentz 		return;
7797da49b602SLuiz Augusto von Dentz 
7798da49b602SLuiz Augusto von Dentz 	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
7799da49b602SLuiz Augusto von Dentz 		return;
7800da49b602SLuiz Augusto von Dentz 
7801da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
7802da49b602SLuiz Augusto von Dentz 
7803da49b602SLuiz Augusto von Dentz 	/* Only count deferred channels with the same PID/PSM */
7804da49b602SLuiz Augusto von Dentz 	if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
7805da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
7806da49b602SLuiz Augusto von Dentz 		return;
7807da49b602SLuiz Augusto von Dentz 
7808da49b602SLuiz Augusto von Dentz 	d->count++;
7809da49b602SLuiz Augusto von Dentz }
7810da49b602SLuiz Augusto von Dentz 
7811162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7812162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
7813162b49e7SJohan Hedberg {
7814162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
7815162b49e7SJohan Hedberg 	struct hci_conn *hcon;
7816162b49e7SJohan Hedberg 	struct hci_dev *hdev;
7817162b49e7SJohan Hedberg 	int err;
7818162b49e7SJohan Hedberg 
781915f02b91SLuiz Augusto von Dentz 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
782015f02b91SLuiz Augusto von Dentz 	       dst, dst_type, __le16_to_cpu(psm), chan->mode);
7821162b49e7SJohan Hedberg 
782239385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
7823162b49e7SJohan Hedberg 	if (!hdev)
7824162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
7825162b49e7SJohan Hedberg 
7826162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
7827162b49e7SJohan Hedberg 
7828162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
7829162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
7830162b49e7SJohan Hedberg 		err = -EINVAL;
7831162b49e7SJohan Hedberg 		goto done;
7832162b49e7SJohan Hedberg 	}
7833162b49e7SJohan Hedberg 
783421626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
783521626e62SJohan Hedberg 		err = -EINVAL;
783621626e62SJohan Hedberg 		goto done;
783721626e62SJohan Hedberg 	}
783821626e62SJohan Hedberg 
783921626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
7840162b49e7SJohan Hedberg 		err = -EINVAL;
7841162b49e7SJohan Hedberg 		goto done;
7842162b49e7SJohan Hedberg 	}
7843162b49e7SJohan Hedberg 
7844162b49e7SJohan Hedberg 	switch (chan->mode) {
7845162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
7846162b49e7SJohan Hedberg 		break;
7847162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
78484be5ca67SLuiz Augusto von Dentz 		break;
784915f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
78504be5ca67SLuiz Augusto von Dentz 		if (!enable_ecred) {
78514be5ca67SLuiz Augusto von Dentz 			err = -EOPNOTSUPP;
78524be5ca67SLuiz Augusto von Dentz 			goto done;
78534be5ca67SLuiz Augusto von Dentz 		}
7854162b49e7SJohan Hedberg 		break;
7855162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
7856162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
7857162b49e7SJohan Hedberg 		if (!disable_ertm)
7858162b49e7SJohan Hedberg 			break;
785919186c7bSGustavo A. R. Silva 		fallthrough;
7860162b49e7SJohan Hedberg 	default:
7861beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
7862162b49e7SJohan Hedberg 		goto done;
7863162b49e7SJohan Hedberg 	}
7864162b49e7SJohan Hedberg 
7865162b49e7SJohan Hedberg 	switch (chan->state) {
7866162b49e7SJohan Hedberg 	case BT_CONNECT:
7867162b49e7SJohan Hedberg 	case BT_CONNECT2:
7868162b49e7SJohan Hedberg 	case BT_CONFIG:
7869162b49e7SJohan Hedberg 		/* Already connecting */
7870162b49e7SJohan Hedberg 		err = 0;
7871162b49e7SJohan Hedberg 		goto done;
7872162b49e7SJohan Hedberg 
7873162b49e7SJohan Hedberg 	case BT_CONNECTED:
7874162b49e7SJohan Hedberg 		/* Already connected */
7875162b49e7SJohan Hedberg 		err = -EISCONN;
7876162b49e7SJohan Hedberg 		goto done;
7877162b49e7SJohan Hedberg 
7878162b49e7SJohan Hedberg 	case BT_OPEN:
7879162b49e7SJohan Hedberg 	case BT_BOUND:
7880162b49e7SJohan Hedberg 		/* Can connect */
7881162b49e7SJohan Hedberg 		break;
7882162b49e7SJohan Hedberg 
7883162b49e7SJohan Hedberg 	default:
7884162b49e7SJohan Hedberg 		err = -EBADFD;
7885162b49e7SJohan Hedberg 		goto done;
7886162b49e7SJohan Hedberg 	}
7887162b49e7SJohan Hedberg 
7888162b49e7SJohan Hedberg 	/* Set destination address and psm */
7889162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
7890162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
7891162b49e7SJohan Hedberg 
7892162b49e7SJohan Hedberg 	chan->psm = psm;
7893162b49e7SJohan Hedberg 	chan->dcid = cid;
7894162b49e7SJohan Hedberg 
78956f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
78966f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
78976f77d8c7SAndre Guedes 		 */
78986f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
78996f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
79006f77d8c7SAndre Guedes 		else
79016f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
79026f77d8c7SAndre Guedes 
7903d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
79040ad06aa6SJohan Hedberg 			hcon = hci_connect_le(hdev, dst, dst_type,
7905fa142220SJakub Pawlowski 					      chan->sec_level,
7906fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
7907082f2300SSzymon Janc 					      HCI_ROLE_SLAVE, NULL);
79080ad06aa6SJohan Hedberg 		else
79090ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
79100ad06aa6SJohan Hedberg 						   chan->sec_level,
791176b13996SManish Mandlik 						   HCI_LE_CONN_TIMEOUT,
791276b13996SManish Mandlik 						   CONN_REASON_L2CAP_CHAN);
79130ad06aa6SJohan Hedberg 
79146f77d8c7SAndre Guedes 	} else {
7915d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
791676b13996SManish Mandlik 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
791776b13996SManish Mandlik 				       CONN_REASON_L2CAP_CHAN);
79186f77d8c7SAndre Guedes 	}
7919162b49e7SJohan Hedberg 
7920162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
7921162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
7922162b49e7SJohan Hedberg 		goto done;
7923162b49e7SJohan Hedberg 	}
7924162b49e7SJohan Hedberg 
7925162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7926162b49e7SJohan Hedberg 	if (!conn) {
7927162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7928162b49e7SJohan Hedberg 		err = -ENOMEM;
7929162b49e7SJohan Hedberg 		goto done;
7930162b49e7SJohan Hedberg 	}
7931162b49e7SJohan Hedberg 
7932da49b602SLuiz Augusto von Dentz 	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
7933da49b602SLuiz Augusto von Dentz 		struct l2cap_chan_data data;
7934da49b602SLuiz Augusto von Dentz 
7935da49b602SLuiz Augusto von Dentz 		data.chan = chan;
7936da49b602SLuiz Augusto von Dentz 		data.pid = chan->ops->get_peer_pid(chan);
7937da49b602SLuiz Augusto von Dentz 		data.count = 1;
7938da49b602SLuiz Augusto von Dentz 
7939da49b602SLuiz Augusto von Dentz 		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
7940da49b602SLuiz Augusto von Dentz 
7941da49b602SLuiz Augusto von Dentz 		/* Check if there isn't too many channels being connected */
7942da49b602SLuiz Augusto von Dentz 		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
7943da49b602SLuiz Augusto von Dentz 			hci_conn_drop(hcon);
7944da49b602SLuiz Augusto von Dentz 			err = -EPROTO;
7945da49b602SLuiz Augusto von Dentz 			goto done;
7946da49b602SLuiz Augusto von Dentz 		}
7947da49b602SLuiz Augusto von Dentz 	}
7948da49b602SLuiz Augusto von Dentz 
794902e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
795002e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
795102e246aeSJohan Hedberg 
7952162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7953162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7954162b49e7SJohan Hedberg 		err = -EBUSY;
795502e246aeSJohan Hedberg 		goto chan_unlock;
7956162b49e7SJohan Hedberg 	}
7957162b49e7SJohan Hedberg 
7958162b49e7SJohan Hedberg 	/* Update source addr of the socket */
7959162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
7960a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
7961162b49e7SJohan Hedberg 
796202e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
7963162b49e7SJohan Hedberg 
7964162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
7965162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
7966162b49e7SJohan Hedberg 
7967162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
7968162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7969162b49e7SJohan Hedberg 
797061202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
797161202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
797261202e4dSJohan Hedberg 	 */
797361202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
797461202e4dSJohan Hedberg 	chan->sport = 0;
797561202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
797661202e4dSJohan Hedberg 
7977162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
7978162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7979162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
7980e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
7981162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
7982162b49e7SJohan Hedberg 		} else
7983162b49e7SJohan Hedberg 			l2cap_do_start(chan);
7984162b49e7SJohan Hedberg 	}
7985162b49e7SJohan Hedberg 
7986162b49e7SJohan Hedberg 	err = 0;
7987162b49e7SJohan Hedberg 
798802e246aeSJohan Hedberg chan_unlock:
7989162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
799002e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
799102e246aeSJohan Hedberg done:
7992162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
7993162b49e7SJohan Hedberg 	hci_dev_put(hdev);
7994162b49e7SJohan Hedberg 	return err;
7995162b49e7SJohan Hedberg }
79966b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7997162b49e7SJohan Hedberg 
799815f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
799915f02b91SLuiz Augusto von Dentz {
800015f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
800115f02b91SLuiz Augusto von Dentz 	struct {
800215f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_reconf_req req;
800315f02b91SLuiz Augusto von Dentz 		__le16 scid;
800415f02b91SLuiz Augusto von Dentz 	} pdu;
800515f02b91SLuiz Augusto von Dentz 
800615f02b91SLuiz Augusto von Dentz 	pdu.req.mtu = cpu_to_le16(chan->imtu);
800715f02b91SLuiz Augusto von Dentz 	pdu.req.mps = cpu_to_le16(chan->mps);
800815f02b91SLuiz Augusto von Dentz 	pdu.scid    = cpu_to_le16(chan->scid);
800915f02b91SLuiz Augusto von Dentz 
801015f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
801115f02b91SLuiz Augusto von Dentz 
801215f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
801315f02b91SLuiz Augusto von Dentz 		       sizeof(pdu), &pdu);
801415f02b91SLuiz Augusto von Dentz }
801515f02b91SLuiz Augusto von Dentz 
801615f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
801715f02b91SLuiz Augusto von Dentz {
801815f02b91SLuiz Augusto von Dentz 	if (chan->imtu > mtu)
801915f02b91SLuiz Augusto von Dentz 		return -EINVAL;
802015f02b91SLuiz Augusto von Dentz 
802115f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
802215f02b91SLuiz Augusto von Dentz 
802315f02b91SLuiz Augusto von Dentz 	chan->imtu = mtu;
802415f02b91SLuiz Augusto von Dentz 
802515f02b91SLuiz Augusto von Dentz 	l2cap_ecred_reconfigure(chan);
802615f02b91SLuiz Augusto von Dentz 
802715f02b91SLuiz Augusto von Dentz 	return 0;
802815f02b91SLuiz Augusto von Dentz }
802915f02b91SLuiz Augusto von Dentz 
80300a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
80310a708f8fSGustavo F. Padovan 
8032686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
80330a708f8fSGustavo F. Padovan {
80340a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
803523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
80360a708f8fSGustavo F. Padovan 
80376ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
80380a708f8fSGustavo F. Padovan 
80390a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
804023691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
804123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
804289bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
80430a708f8fSGustavo F. Padovan 			continue;
80440a708f8fSGustavo F. Padovan 
80457eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
80460a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
804743bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
80480a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
80490a708f8fSGustavo F. Padovan 			exact++;
80507eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
80510a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
805243bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
80530a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
80540a708f8fSGustavo F. Padovan 		}
80550a708f8fSGustavo F. Padovan 	}
805623691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
80570a708f8fSGustavo F. Padovan 
80580a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
80590a708f8fSGustavo F. Padovan }
80600a708f8fSGustavo F. Padovan 
8061e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
8062e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
8063e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
8064e760ec12SJohan Hedberg  */
8065e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
8066327a7191SJohan Hedberg 						  struct hci_conn *hcon)
8067e760ec12SJohan Hedberg {
8068327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
8069327a7191SJohan Hedberg 
8070e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
8071e760ec12SJohan Hedberg 
8072e760ec12SJohan Hedberg 	if (c)
8073e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
8074e760ec12SJohan Hedberg 	else
8075e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
8076e760ec12SJohan Hedberg 
8077e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
8078e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
8079e760ec12SJohan Hedberg 			continue;
8080e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
8081e760ec12SJohan Hedberg 			continue;
8082327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
8083e760ec12SJohan Hedberg 			continue;
8084327a7191SJohan Hedberg 		if (src_type != c->src_type)
808554a1b626SJohan Hedberg 			continue;
8086e760ec12SJohan Hedberg 
8087e760ec12SJohan Hedberg 		l2cap_chan_hold(c);
8088e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
8089e760ec12SJohan Hedberg 		return c;
8090e760ec12SJohan Hedberg 	}
8091e760ec12SJohan Hedberg 
8092e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
8093e760ec12SJohan Hedberg 
8094e760ec12SJohan Hedberg 	return NULL;
8095e760ec12SJohan Hedberg }
8096e760ec12SJohan Hedberg 
8097539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
80980a708f8fSGustavo F. Padovan {
8099e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
81000a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
8101e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
8102e760ec12SJohan Hedberg 	u8 dst_type;
81030a708f8fSGustavo F. Padovan 
8104539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
8105539c496dSJohan Hedberg 		return;
8106539c496dSJohan Hedberg 
81076ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
81080a708f8fSGustavo F. Padovan 
8109dc0f5088SJohan Hedberg 	if (status) {
8110e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
8111dc0f5088SJohan Hedberg 		return;
8112ba6fc317SAndrei Emeltchenko 	}
8113dc0f5088SJohan Hedberg 
8114dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
8115dc0f5088SJohan Hedberg 	if (!conn)
8116dc0f5088SJohan Hedberg 		return;
8117dc0f5088SJohan Hedberg 
8118a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
8119e760ec12SJohan Hedberg 
8120e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
8121e760ec12SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
8122e760ec12SJohan Hedberg 		return;
8123e760ec12SJohan Hedberg 
8124e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
8125e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
8126e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
8127e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
8128e760ec12SJohan Hedberg 	 */
8129327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
8130e760ec12SJohan Hedberg 	while (pchan) {
8131e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
8132e760ec12SJohan Hedberg 
8133e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
8134e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
8135e760ec12SJohan Hedberg 			goto next;
8136e760ec12SJohan Hedberg 
8137e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
8138e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
8139e760ec12SJohan Hedberg 		if (chan) {
8140e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
8141e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
8142a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
8143e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
8144e760ec12SJohan Hedberg 
8145e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
8146e760ec12SJohan Hedberg 		}
8147e760ec12SJohan Hedberg 
8148e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
8149e760ec12SJohan Hedberg next:
8150327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
8151e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
8152e760ec12SJohan Hedberg 		pchan = next;
8153e760ec12SJohan Hedberg 	}
8154e760ec12SJohan Hedberg 
8155dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
81560a708f8fSGustavo F. Padovan }
81570a708f8fSGustavo F. Padovan 
8158686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
81590a708f8fSGustavo F. Padovan {
81600a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
81610a708f8fSGustavo F. Padovan 
81620a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
81630a708f8fSGustavo F. Padovan 
8164686ebf28SUlisses Furquim 	if (!conn)
81659f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
81660a708f8fSGustavo F. Padovan 	return conn->disc_reason;
81670a708f8fSGustavo F. Padovan }
81680a708f8fSGustavo F. Padovan 
81693a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
81700a708f8fSGustavo F. Padovan {
81713a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
81723a6d576bSJohan Hedberg 		return;
81733a6d576bSJohan Hedberg 
81740a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
81750a708f8fSGustavo F. Padovan 
8176e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
81770a708f8fSGustavo F. Padovan }
81780a708f8fSGustavo F. Padovan 
81794343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
81800a708f8fSGustavo F. Padovan {
8181715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
81820a708f8fSGustavo F. Padovan 		return;
81830a708f8fSGustavo F. Padovan 
81840a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
81854343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
8186ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
81877d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
81887d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
81890f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
81900a708f8fSGustavo F. Padovan 	} else {
81914343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
8192c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
81930a708f8fSGustavo F. Padovan 	}
81940a708f8fSGustavo F. Padovan }
81950a708f8fSGustavo F. Padovan 
8196354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
81970a708f8fSGustavo F. Padovan {
81980a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
819948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
82000a708f8fSGustavo F. Padovan 
82010a708f8fSGustavo F. Padovan 	if (!conn)
8202354fe804SJohan Hedberg 		return;
82030a708f8fSGustavo F. Padovan 
820489d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
82050a708f8fSGustavo F. Padovan 
82063df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
82070a708f8fSGustavo F. Padovan 
82083df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
82096be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
82100a708f8fSGustavo F. Padovan 
821189d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
821289d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
8213f1cb9af5SVinicius Costa Gomes 
82142338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
821578eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
821678eb2f98SAndrei Emeltchenko 			continue;
821778eb2f98SAndrei Emeltchenko 		}
821878eb2f98SAndrei Emeltchenko 
8219191eb398SJohan Hedberg 		if (!status && encrypt)
8220f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
8221f1cb9af5SVinicius Costa Gomes 
822296eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
82236be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
82240a708f8fSGustavo F. Padovan 			continue;
82250a708f8fSGustavo F. Padovan 		}
82260a708f8fSGustavo F. Padovan 
822789bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
822889bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
8229d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
82304343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
82316be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
82320a708f8fSGustavo F. Padovan 			continue;
82330a708f8fSGustavo F. Padovan 		}
82340a708f8fSGustavo F. Padovan 
823589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
8236693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
823793c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
82386d3c15daSJohan Hedberg 			else
8239ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8240fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
824115f02b91SLuiz Augusto von Dentz 			   !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
824215f02b91SLuiz Augusto von Dentz 			     chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
82430a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
8244df3c3931SJohan Hedberg 			__u16 res, stat;
82450a708f8fSGustavo F. Padovan 
8246693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
8247bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
8248df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
8249df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
82502dc4e510SGustavo Padovan 					chan->ops->defer(chan);
8251df3c3931SJohan Hedberg 				} else {
8252acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
8253df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
8254df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
8255df3c3931SJohan Hedberg 				}
82560a708f8fSGustavo F. Padovan 			} else {
8257acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
8258ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8259df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
8260df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
82610a708f8fSGustavo F. Padovan 			}
82620a708f8fSGustavo F. Padovan 
8263fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
8264fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
8265df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
8266df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
8267fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
8268fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
82692d369359SMat Martineau 
82702d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
82712d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
82722d369359SMat Martineau 				char buf[128];
82732d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
82742d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
82752d369359SMat Martineau 					       L2CAP_CONF_REQ,
8276e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
82772d369359SMat Martineau 					       buf);
82782d369359SMat Martineau 				chan->num_conf_req++;
82792d369359SMat Martineau 			}
82800a708f8fSGustavo F. Padovan 		}
82810a708f8fSGustavo F. Padovan 
82826be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
82830a708f8fSGustavo F. Padovan 	}
82840a708f8fSGustavo F. Padovan 
82853df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
82860a708f8fSGustavo F. Padovan }
82870a708f8fSGustavo F. Padovan 
82884d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
82894d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
82904d7ea8eeSLuiz Augusto von Dentz 			   u16 len)
82914d7ea8eeSLuiz Augusto von Dentz {
82924d7ea8eeSLuiz Augusto von Dentz 	if (!conn->rx_skb) {
82934d7ea8eeSLuiz Augusto von Dentz 		/* Allocate skb for the complete frame (with header) */
82944d7ea8eeSLuiz Augusto von Dentz 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
82954d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb)
82964d7ea8eeSLuiz Augusto von Dentz 			return -ENOMEM;
82974d7ea8eeSLuiz Augusto von Dentz 		/* Init rx_len */
82984d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len;
82994d7ea8eeSLuiz Augusto von Dentz 	}
83004d7ea8eeSLuiz Augusto von Dentz 
83014d7ea8eeSLuiz Augusto von Dentz 	/* Copy as much as the rx_skb can hold */
83024d7ea8eeSLuiz Augusto von Dentz 	len = min_t(u16, len, skb->len);
83034d7ea8eeSLuiz Augusto von Dentz 	skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
83044d7ea8eeSLuiz Augusto von Dentz 	skb_pull(skb, len);
83054d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len -= len;
83064d7ea8eeSLuiz Augusto von Dentz 
83074d7ea8eeSLuiz Augusto von Dentz 	return len;
83084d7ea8eeSLuiz Augusto von Dentz }
83094d7ea8eeSLuiz Augusto von Dentz 
83104d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
83114d7ea8eeSLuiz Augusto von Dentz {
83124d7ea8eeSLuiz Augusto von Dentz 	struct sk_buff *rx_skb;
83134d7ea8eeSLuiz Augusto von Dentz 	int len;
83144d7ea8eeSLuiz Augusto von Dentz 
83154d7ea8eeSLuiz Augusto von Dentz 	/* Append just enough to complete the header */
83164d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
83174d7ea8eeSLuiz Augusto von Dentz 
83184d7ea8eeSLuiz Augusto von Dentz 	/* If header could not be read just continue */
83194d7ea8eeSLuiz Augusto von Dentz 	if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
83204d7ea8eeSLuiz Augusto von Dentz 		return len;
83214d7ea8eeSLuiz Augusto von Dentz 
83224d7ea8eeSLuiz Augusto von Dentz 	rx_skb = conn->rx_skb;
83234d7ea8eeSLuiz Augusto von Dentz 	len = get_unaligned_le16(rx_skb->data);
83244d7ea8eeSLuiz Augusto von Dentz 
83254d7ea8eeSLuiz Augusto von Dentz 	/* Check if rx_skb has enough space to received all fragments */
83264d7ea8eeSLuiz Augusto von Dentz 	if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
83274d7ea8eeSLuiz Augusto von Dentz 		/* Update expected len */
83284d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
83294d7ea8eeSLuiz Augusto von Dentz 		return L2CAP_LEN_SIZE;
83304d7ea8eeSLuiz Augusto von Dentz 	}
83314d7ea8eeSLuiz Augusto von Dentz 
83324d7ea8eeSLuiz Augusto von Dentz 	/* Reset conn->rx_skb since it will need to be reallocated in order to
83334d7ea8eeSLuiz Augusto von Dentz 	 * fit all fragments.
83344d7ea8eeSLuiz Augusto von Dentz 	 */
83354d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
83364d7ea8eeSLuiz Augusto von Dentz 
83374d7ea8eeSLuiz Augusto von Dentz 	/* Reallocates rx_skb using the exact expected length */
83384d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, rx_skb,
83394d7ea8eeSLuiz Augusto von Dentz 			      len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
83404d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(rx_skb);
83414d7ea8eeSLuiz Augusto von Dentz 
83424d7ea8eeSLuiz Augusto von Dentz 	return len;
83434d7ea8eeSLuiz Augusto von Dentz }
83444d7ea8eeSLuiz Augusto von Dentz 
83454d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
83464d7ea8eeSLuiz Augusto von Dentz {
83474d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(conn->rx_skb);
83484d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
83494d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len = 0;
83504d7ea8eeSLuiz Augusto von Dentz }
83514d7ea8eeSLuiz Augusto von Dentz 
83529b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
83530a708f8fSGustavo F. Padovan {
83540a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
8355d73a0988SAndrei Emeltchenko 	int len;
83560a708f8fSGustavo F. Padovan 
83571d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
8358ca8bee5dSMarcel Holtmann 	if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
83591d13a254SAndrei Emeltchenko 		goto drop;
83600a708f8fSGustavo F. Padovan 
83610a708f8fSGustavo F. Padovan 	if (!conn)
8362baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
83630a708f8fSGustavo F. Padovan 
83640a708f8fSGustavo F. Padovan 	if (!conn)
83650a708f8fSGustavo F. Padovan 		goto drop;
83660a708f8fSGustavo F. Padovan 
83670a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
83680a708f8fSGustavo F. Padovan 
8369d73a0988SAndrei Emeltchenko 	switch (flags) {
8370d73a0988SAndrei Emeltchenko 	case ACL_START:
8371d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
8372d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
83734d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb) {
83740a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
83754d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
83760a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
83770a708f8fSGustavo F. Padovan 		}
83780a708f8fSGustavo F. Padovan 
83794d7ea8eeSLuiz Augusto von Dentz 		/* Start fragment may not contain the L2CAP length so just
83804d7ea8eeSLuiz Augusto von Dentz 		 * copy the initial byte when that happens and use conn->mtu as
83814d7ea8eeSLuiz Augusto von Dentz 		 * expected length.
83824d7ea8eeSLuiz Augusto von Dentz 		 */
83834d7ea8eeSLuiz Augusto von Dentz 		if (skb->len < L2CAP_LEN_SIZE) {
83844d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_frag(conn, skb, conn->mtu) < 0)
83850a708f8fSGustavo F. Padovan 				goto drop;
83864d7ea8eeSLuiz Augusto von Dentz 			return;
83870a708f8fSGustavo F. Padovan 		}
83880a708f8fSGustavo F. Padovan 
83894d7ea8eeSLuiz Augusto von Dentz 		len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
83900a708f8fSGustavo F. Padovan 
83910a708f8fSGustavo F. Padovan 		if (len == skb->len) {
83920a708f8fSGustavo F. Padovan 			/* Complete frame received */
83930a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
83949b4c3336SArron Wang 			return;
83950a708f8fSGustavo F. Padovan 		}
83960a708f8fSGustavo F. Padovan 
83970a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
83980a708f8fSGustavo F. Padovan 
83990a708f8fSGustavo F. Padovan 		if (skb->len > len) {
84000a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
84010a708f8fSGustavo F. Padovan 			       skb->len, len);
84020a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
84030a708f8fSGustavo F. Padovan 			goto drop;
84040a708f8fSGustavo F. Padovan 		}
84050a708f8fSGustavo F. Padovan 
84064d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
84074d7ea8eeSLuiz Augusto von Dentz 		if (l2cap_recv_frag(conn, skb, len) < 0)
84080a708f8fSGustavo F. Padovan 			goto drop;
84090a708f8fSGustavo F. Padovan 
8410d73a0988SAndrei Emeltchenko 		break;
8411d73a0988SAndrei Emeltchenko 
8412d73a0988SAndrei Emeltchenko 	case ACL_CONT:
84130a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
84140a708f8fSGustavo F. Padovan 
84154d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb) {
84160a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
84170a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
84180a708f8fSGustavo F. Padovan 			goto drop;
84190a708f8fSGustavo F. Padovan 		}
84200a708f8fSGustavo F. Padovan 
84214d7ea8eeSLuiz Augusto von Dentz 		/* Complete the L2CAP length if it has not been read */
84224d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
84234d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_len(conn, skb) < 0) {
84240a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
84250a708f8fSGustavo F. Padovan 				goto drop;
84260a708f8fSGustavo F. Padovan 			}
84270a708f8fSGustavo F. Padovan 
84284d7ea8eeSLuiz Augusto von Dentz 			/* Header still could not be read just continue */
84294d7ea8eeSLuiz Augusto von Dentz 			if (conn->rx_skb->len < L2CAP_LEN_SIZE)
84304d7ea8eeSLuiz Augusto von Dentz 				return;
84314d7ea8eeSLuiz Augusto von Dentz 		}
84324d7ea8eeSLuiz Augusto von Dentz 
84334d7ea8eeSLuiz Augusto von Dentz 		if (skb->len > conn->rx_len) {
84344d7ea8eeSLuiz Augusto von Dentz 			BT_ERR("Fragment is too long (len %d, expected %d)",
84354d7ea8eeSLuiz Augusto von Dentz 			       skb->len, conn->rx_len);
84364d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
84374d7ea8eeSLuiz Augusto von Dentz 			l2cap_conn_unreliable(conn, ECOMM);
84384d7ea8eeSLuiz Augusto von Dentz 			goto drop;
84394d7ea8eeSLuiz Augusto von Dentz 		}
84404d7ea8eeSLuiz Augusto von Dentz 
84414d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
84424d7ea8eeSLuiz Augusto von Dentz 		l2cap_recv_frag(conn, skb, skb->len);
84430a708f8fSGustavo F. Padovan 
84440a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
8445c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
8446c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
8447c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
8448c4e5bafaSJohan Hedberg 			 */
8449c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
84500a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
8451c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
84520a708f8fSGustavo F. Padovan 		}
8453d73a0988SAndrei Emeltchenko 		break;
84540a708f8fSGustavo F. Padovan 	}
84550a708f8fSGustavo F. Padovan 
84560a708f8fSGustavo F. Padovan drop:
84570a708f8fSGustavo F. Padovan 	kfree_skb(skb);
84580a708f8fSGustavo F. Padovan }
84590a708f8fSGustavo F. Padovan 
8460354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
8461354fe804SJohan Hedberg 	.name		= "L2CAP",
8462539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
84633a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
8464354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
8465354fe804SJohan Hedberg };
8466354fe804SJohan Hedberg 
84670a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
84680a708f8fSGustavo F. Padovan {
846923691d75SGustavo F. Padovan 	struct l2cap_chan *c;
84700a708f8fSGustavo F. Padovan 
8471333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
84720a708f8fSGustavo F. Padovan 
847323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
8474eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
8475eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
847689bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
847723691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
847823691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
84790a708f8fSGustavo F. Padovan 	}
84800a708f8fSGustavo F. Padovan 
8481333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
84820a708f8fSGustavo F. Padovan 
84830a708f8fSGustavo F. Padovan 	return 0;
84840a708f8fSGustavo F. Padovan }
84850a708f8fSGustavo F. Padovan 
84868e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
84870a708f8fSGustavo F. Padovan 
84880a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
84890a708f8fSGustavo F. Padovan 
849064274518SGustavo F. Padovan int __init l2cap_init(void)
84910a708f8fSGustavo F. Padovan {
84920a708f8fSGustavo F. Padovan 	int err;
84930a708f8fSGustavo F. Padovan 
8494bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
84950a708f8fSGustavo F. Padovan 	if (err < 0)
84960a708f8fSGustavo F. Padovan 		return err;
84970a708f8fSGustavo F. Padovan 
8498354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
8499354fe804SJohan Hedberg 
85001120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
85011120e4bfSMarcel Holtmann 		return 0;
85021120e4bfSMarcel Holtmann 
85032d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
85042d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
85050a708f8fSGustavo F. Padovan 
85060a708f8fSGustavo F. Padovan 	return 0;
85070a708f8fSGustavo F. Padovan }
85080a708f8fSGustavo F. Padovan 
850964274518SGustavo F. Padovan void l2cap_exit(void)
85100a708f8fSGustavo F. Padovan {
85110a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
8512354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
8513bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
85140a708f8fSGustavo F. Padovan }
85150a708f8fSGustavo F. Padovan 
85160a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
85170a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
85184be5ca67SLuiz Augusto von Dentz 
85194be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
85204be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
8521