xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 7ccca396)
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"
420a708f8fSGustavo F. Padovan 
430f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535
440f1bfe4eSJohan Hedberg 
45d1de6d46SMat Martineau bool disable_ertm;
46462fcd53SLuiz Augusto von Dentz bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_ECRED);
470a708f8fSGustavo F. Padovan 
48547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
490a708f8fSGustavo F. Padovan 
50b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
51b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
520a708f8fSGustavo F. Padovan 
530a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
540a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
554519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
564519de9aSGustavo F. Padovan 			   void *data);
57e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
585e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
590a708f8fSGustavo F. Padovan 
60d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
61608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
622d2cb306STetsuo Handa static void l2cap_retrans_timeout(struct work_struct *work);
632d2cb306STetsuo Handa static void l2cap_monitor_timeout(struct work_struct *work);
642d2cb306STetsuo Handa static void l2cap_ack_timeout(struct work_struct *work);
65608bcc6dSMat Martineau 
bdaddr_type(u8 link_type,u8 bdaddr_type)66a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
674f1654e0SMarcel Holtmann {
68a250e048SJohan Hedberg 	if (link_type == LE_LINK) {
69a250e048SJohan Hedberg 		if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
704f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
714f1654e0SMarcel Holtmann 		else
724f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
734f1654e0SMarcel Holtmann 	}
744f1654e0SMarcel Holtmann 
754f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
764f1654e0SMarcel Holtmann }
774f1654e0SMarcel Holtmann 
bdaddr_src_type(struct hci_conn * hcon)78a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
79a250e048SJohan Hedberg {
80a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->src_type);
81a250e048SJohan Hedberg }
82a250e048SJohan Hedberg 
bdaddr_dst_type(struct hci_conn * hcon)83a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
84a250e048SJohan Hedberg {
85a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->dst_type);
86a250e048SJohan Hedberg }
87a250e048SJohan Hedberg 
880a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8971ba0e56SGustavo F. Padovan 
__l2cap_get_chan_by_dcid(struct l2cap_conn * conn,u16 cid)902d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
912d792818SGustavo Padovan 						   u16 cid)
920a708f8fSGustavo F. Padovan {
933df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
94baa7e1faSGustavo F. Padovan 
953df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
963df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
973df91ea2SAndrei Emeltchenko 			return c;
980a708f8fSGustavo F. Padovan 	}
993df91ea2SAndrei Emeltchenko 	return NULL;
100baa7e1faSGustavo F. Padovan }
1010a708f8fSGustavo F. Padovan 
__l2cap_get_chan_by_scid(struct l2cap_conn * conn,u16 cid)1022d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1032d792818SGustavo Padovan 						   u16 cid)
1040a708f8fSGustavo F. Padovan {
1053df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
106baa7e1faSGustavo F. Padovan 
1073df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1083df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
1093df91ea2SAndrei Emeltchenko 			return c;
1100a708f8fSGustavo F. Padovan 	}
1113df91ea2SAndrei Emeltchenko 	return NULL;
112baa7e1faSGustavo F. Padovan }
1130a708f8fSGustavo F. Padovan 
1140a708f8fSGustavo F. Padovan /* Find channel with given SCID.
115d0be8347SLuiz Augusto von Dentz  * Returns a reference locked channel.
116d0be8347SLuiz Augusto von Dentz  */
l2cap_get_chan_by_scid(struct l2cap_conn * conn,u16 cid)1172d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1182d792818SGustavo Padovan 						 u16 cid)
1190a708f8fSGustavo F. Padovan {
12048454079SGustavo F. Padovan 	struct l2cap_chan *c;
121baa7e1faSGustavo F. Padovan 
1223df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
123baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
124d0be8347SLuiz Augusto von Dentz 	if (c) {
125d0be8347SLuiz Augusto von Dentz 		/* Only lock if chan reference is not 0 */
126d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
127ef191adeSMat Martineau 		if (c)
128ef191adeSMat Martineau 			l2cap_chan_lock(c);
129d0be8347SLuiz Augusto von Dentz 	}
1303df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1313df91ea2SAndrei Emeltchenko 
13248454079SGustavo F. Padovan 	return c;
1330a708f8fSGustavo F. Padovan }
1340a708f8fSGustavo F. Padovan 
135b1a130b7SMat Martineau /* Find channel with given DCID.
136d0be8347SLuiz Augusto von Dentz  * Returns a reference locked channel.
137b1a130b7SMat Martineau  */
l2cap_get_chan_by_dcid(struct l2cap_conn * conn,u16 cid)138b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
139b1a130b7SMat Martineau 						 u16 cid)
140b1a130b7SMat Martineau {
141b1a130b7SMat Martineau 	struct l2cap_chan *c;
142b1a130b7SMat Martineau 
143b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
144b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
145d0be8347SLuiz Augusto von Dentz 	if (c) {
146d0be8347SLuiz Augusto von Dentz 		/* Only lock if chan reference is not 0 */
147d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
148b1a130b7SMat Martineau 		if (c)
149b1a130b7SMat Martineau 			l2cap_chan_lock(c);
150d0be8347SLuiz Augusto von Dentz 	}
151b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
152b1a130b7SMat Martineau 
153b1a130b7SMat Martineau 	return c;
154b1a130b7SMat Martineau }
155b1a130b7SMat Martineau 
__l2cap_get_chan_by_ident(struct l2cap_conn * conn,u8 ident)1562d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1572d792818SGustavo Padovan 						    u8 ident)
1580a708f8fSGustavo F. Padovan {
1593df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
160baa7e1faSGustavo F. Padovan 
1613df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1623df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1633df91ea2SAndrei Emeltchenko 			return c;
1640a708f8fSGustavo F. Padovan 	}
1653df91ea2SAndrei Emeltchenko 	return NULL;
166baa7e1faSGustavo F. Padovan }
1670a708f8fSGustavo F. Padovan 
__l2cap_global_chan_by_addr(__le16 psm,bdaddr_t * src,u8 src_type)16800f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
16900f62726SLuiz Augusto von Dentz 						      u8 src_type)
1709e4425ffSGustavo F. Padovan {
17123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1729e4425ffSGustavo F. Padovan 
17323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
17400f62726SLuiz Augusto von Dentz 		if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17500f62726SLuiz Augusto von Dentz 			continue;
17600f62726SLuiz Augusto von Dentz 
17700f62726SLuiz Augusto von Dentz 		if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
17800f62726SLuiz Augusto von Dentz 			continue;
17900f62726SLuiz Augusto von Dentz 
1807eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
18123691d75SGustavo F. Padovan 			return c;
1829e4425ffSGustavo F. Padovan 	}
183250938cbSSzymon Janc 	return NULL;
184250938cbSSzymon Janc }
1859e4425ffSGustavo F. Padovan 
l2cap_add_psm(struct l2cap_chan * chan,bdaddr_t * src,__le16 psm)1869e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1879e4425ffSGustavo F. Padovan {
18873b2ec18SGustavo F. Padovan 	int err;
18973b2ec18SGustavo F. Padovan 
190333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1919e4425ffSGustavo F. Padovan 
19200f62726SLuiz Augusto von Dentz 	if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
19373b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
19473b2ec18SGustavo F. Padovan 		goto done;
1959e4425ffSGustavo F. Padovan 	}
1969e4425ffSGustavo F. Padovan 
19773b2ec18SGustavo F. Padovan 	if (psm) {
1989e4425ffSGustavo F. Padovan 		chan->psm = psm;
1999e4425ffSGustavo F. Padovan 		chan->sport = psm;
20073b2ec18SGustavo F. Padovan 		err = 0;
20173b2ec18SGustavo F. Padovan 	} else {
20292594a51SJohan Hedberg 		u16 p, start, end, incr;
20392594a51SJohan Hedberg 
20492594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
20592594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
20692594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
20792594a51SJohan Hedberg 			incr = 2;
20892594a51SJohan Hedberg 		} else {
20992594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
21092594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
21192594a51SJohan Hedberg 			incr = 1;
21292594a51SJohan Hedberg 		}
2139e4425ffSGustavo F. Padovan 
21473b2ec18SGustavo F. Padovan 		err = -EINVAL;
21592594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
21600f62726SLuiz Augusto von Dentz 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
21700f62726SLuiz Augusto von Dentz 							 chan->src_type)) {
21873b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
21973b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
22073b2ec18SGustavo F. Padovan 				err = 0;
22173b2ec18SGustavo F. Padovan 				break;
22273b2ec18SGustavo F. Padovan 			}
22373b2ec18SGustavo F. Padovan 	}
22473b2ec18SGustavo F. Padovan 
22573b2ec18SGustavo F. Padovan done:
226333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
22773b2ec18SGustavo F. Padovan 	return err;
2289e4425ffSGustavo F. Padovan }
2296b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2309e4425ffSGustavo F. Padovan 
l2cap_add_scid(struct l2cap_chan * chan,__u16 scid)2319e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2329e4425ffSGustavo F. Padovan {
233333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2349e4425ffSGustavo F. Padovan 
23514824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
23614824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
23714824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
23814824308SJohan Hedberg 
2399e4425ffSGustavo F. Padovan 	chan->scid = scid;
2409e4425ffSGustavo F. Padovan 
241333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2429e4425ffSGustavo F. Padovan 
2439e4425ffSGustavo F. Padovan 	return 0;
2449e4425ffSGustavo F. Padovan }
2459e4425ffSGustavo F. Padovan 
l2cap_alloc_cid(struct l2cap_conn * conn)246baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2470a708f8fSGustavo F. Padovan {
248e77af755SJohan Hedberg 	u16 cid, dyn_end;
2490a708f8fSGustavo F. Padovan 
250e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
251e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
252e77af755SJohan Hedberg 	else
253e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
254e77af755SJohan Hedberg 
255ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
256baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2570a708f8fSGustavo F. Padovan 			return cid;
2580a708f8fSGustavo F. Padovan 	}
2590a708f8fSGustavo F. Padovan 
2600a708f8fSGustavo F. Padovan 	return 0;
2610a708f8fSGustavo F. Padovan }
2620a708f8fSGustavo F. Padovan 
l2cap_state_change(struct l2cap_chan * chan,int state)263f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26489bc500eSGustavo F. Padovan {
26542d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
266badaaa00SGustavo F. Padovan 	       state_to_string(state));
267badaaa00SGustavo F. Padovan 
26889bc500eSGustavo F. Padovan 	chan->state = state;
26953f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
27089bc500eSGustavo F. Padovan }
27189bc500eSGustavo F. Padovan 
l2cap_state_change_and_error(struct l2cap_chan * chan,int state,int err)272f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
273f8e73017SGustavo Padovan 						int state, int err)
2742e0052e4SAndrei Emeltchenko {
275f8e73017SGustavo Padovan 	chan->state = state;
27653f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2772e0052e4SAndrei Emeltchenko }
2782e0052e4SAndrei Emeltchenko 
l2cap_chan_set_err(struct l2cap_chan * chan,int err)2792e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2802e0052e4SAndrei Emeltchenko {
281f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2822e0052e4SAndrei Emeltchenko }
2832e0052e4SAndrei Emeltchenko 
__set_retrans_timer(struct l2cap_chan * chan)2844239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2854239d16fSMat Martineau {
2864239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2874239d16fSMat Martineau 	    chan->retrans_timeout) {
2884239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2894239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2904239d16fSMat Martineau 	}
2914239d16fSMat Martineau }
2924239d16fSMat Martineau 
__set_monitor_timer(struct l2cap_chan * chan)2934239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2944239d16fSMat Martineau {
2954239d16fSMat Martineau 	__clear_retrans_timer(chan);
2964239d16fSMat Martineau 	if (chan->monitor_timeout) {
2974239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2984239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2994239d16fSMat Martineau 	}
3004239d16fSMat Martineau }
3014239d16fSMat Martineau 
l2cap_ertm_seq_in_queue(struct sk_buff_head * head,u16 seq)302608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
303608bcc6dSMat Martineau 					       u16 seq)
304608bcc6dSMat Martineau {
305608bcc6dSMat Martineau 	struct sk_buff *skb;
306608bcc6dSMat Martineau 
307608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
308a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
309608bcc6dSMat Martineau 			return skb;
310608bcc6dSMat Martineau 	}
311608bcc6dSMat Martineau 
312608bcc6dSMat Martineau 	return NULL;
313608bcc6dSMat Martineau }
314608bcc6dSMat Martineau 
3153c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3163c588192SMat Martineau 
3173c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3183c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3193c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3203c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3213c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3223c588192SMat Martineau  * and removed from the head in constant time, without further memory
3233c588192SMat Martineau  * allocs or frees.
3243c588192SMat Martineau  */
3253c588192SMat Martineau 
l2cap_seq_list_init(struct l2cap_seq_list * seq_list,u16 size)3263c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3273c588192SMat Martineau {
3283c588192SMat Martineau 	size_t alloc_size, i;
3293c588192SMat Martineau 
3303c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3313c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3323c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3333c588192SMat Martineau 	 */
3343c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3353c588192SMat Martineau 
3366da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3373c588192SMat Martineau 	if (!seq_list->list)
3383c588192SMat Martineau 		return -ENOMEM;
3393c588192SMat Martineau 
3403c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3413c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3423c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3433c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3443c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3453c588192SMat Martineau 
3463c588192SMat Martineau 	return 0;
3473c588192SMat Martineau }
3483c588192SMat Martineau 
l2cap_seq_list_free(struct l2cap_seq_list * seq_list)3493c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3503c588192SMat Martineau {
3513c588192SMat Martineau 	kfree(seq_list->list);
3523c588192SMat Martineau }
3533c588192SMat Martineau 
l2cap_seq_list_contains(struct l2cap_seq_list * seq_list,u16 seq)3543c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3553c588192SMat Martineau 					   u16 seq)
3563c588192SMat Martineau {
3573c588192SMat Martineau 	/* Constant-time check for list membership */
3583c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3593c588192SMat Martineau }
3603c588192SMat Martineau 
l2cap_seq_list_pop(struct l2cap_seq_list * seq_list)36103a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3623c588192SMat Martineau {
36303a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3643c588192SMat Martineau 	u16 mask = seq_list->mask;
3653c588192SMat Martineau 
3663c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3673c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3683c588192SMat Martineau 
3693c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3703c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3713c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3723c588192SMat Martineau 	}
3733c588192SMat Martineau 
3743c588192SMat Martineau 	return seq;
3753c588192SMat Martineau }
3763c588192SMat Martineau 
l2cap_seq_list_clear(struct l2cap_seq_list * seq_list)3773c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3783c588192SMat Martineau {
3793c588192SMat Martineau 	u16 i;
380f522ae36SGustavo Padovan 
381f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
382f522ae36SGustavo Padovan 		return;
383f522ae36SGustavo Padovan 
3843c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3853c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3863c588192SMat Martineau 
3873c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3883c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3893c588192SMat Martineau }
3903c588192SMat Martineau 
l2cap_seq_list_append(struct l2cap_seq_list * seq_list,u16 seq)3913c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3923c588192SMat Martineau {
3933c588192SMat Martineau 	u16 mask = seq_list->mask;
3943c588192SMat Martineau 
3953c588192SMat Martineau 	/* All appends happen in constant time */
3963c588192SMat Martineau 
397f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
398f522ae36SGustavo Padovan 		return;
399f522ae36SGustavo Padovan 
4003c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4013c588192SMat Martineau 		seq_list->head = seq;
4023c588192SMat Martineau 	else
4033c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
4043c588192SMat Martineau 
4053c588192SMat Martineau 	seq_list->tail = seq;
4063c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4073c588192SMat Martineau }
4083c588192SMat Martineau 
l2cap_chan_timeout(struct work_struct * work)409721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
410ab07801dSGustavo F. Padovan {
411721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
412721c4181SGustavo F. Padovan 					       chan_timer.work);
4133df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
414ab07801dSGustavo F. Padovan 	int reason;
415ab07801dSGustavo F. Padovan 
416e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
417ab07801dSGustavo F. Padovan 
418955b5b6cSDuoming Zhou 	if (!conn)
419955b5b6cSDuoming Zhou 		return;
420955b5b6cSDuoming Zhou 
4213df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4226c08fc89SManish Mandlik 	/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4236c08fc89SManish Mandlik 	 * this work. No need to call l2cap_chan_hold(chan) here again.
4246c08fc89SManish Mandlik 	 */
4256be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
426ab07801dSGustavo F. Padovan 
42789bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
428ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
42989bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
430ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
431ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
432ab07801dSGustavo F. Padovan 	else
433ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
434ab07801dSGustavo F. Padovan 
4350f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
436ab07801dSGustavo F. Padovan 
43780b98027SGustavo Padovan 	chan->ops->close(chan);
4383df91ea2SAndrei Emeltchenko 
4396c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
440371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4416c08fc89SManish Mandlik 
4426c08fc89SManish Mandlik 	mutex_unlock(&conn->chan_lock);
443ab07801dSGustavo F. Padovan }
444ab07801dSGustavo F. Padovan 
l2cap_chan_create(void)445eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4460a708f8fSGustavo F. Padovan {
44748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4480a708f8fSGustavo F. Padovan 
44948454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
45048454079SGustavo F. Padovan 	if (!chan)
45148454079SGustavo F. Padovan 		return NULL;
4520a708f8fSGustavo F. Padovan 
453be859723STetsuo Handa 	skb_queue_head_init(&chan->tx_q);
454be859723STetsuo Handa 	skb_queue_head_init(&chan->srej_q);
455c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
456c03b355eSAndrei Emeltchenko 
457ff714119SJohan Hedberg 	/* Set default lock nesting level */
458ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
459ff714119SJohan Hedberg 
460e2310343SSebastian Urban 	/* Available receive buffer space is initially unknown */
461e2310343SSebastian Urban 	chan->rx_avail = -1;
462e2310343SSebastian Urban 
463333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46423691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
465333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
46623691d75SGustavo F. Padovan 
467721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
4682d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
4692d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
4702d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
471ab07801dSGustavo F. Padovan 
47289bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
47389bc500eSGustavo F. Padovan 
474144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
47571ba0e56SGustavo F. Padovan 
4762827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4772827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4782827011fSMat Martineau 
479eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
480abc545b8SSzymon Janc 
48148454079SGustavo F. Padovan 	return chan;
4820a708f8fSGustavo F. Padovan }
4836b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4840a708f8fSGustavo F. Padovan 
l2cap_chan_destroy(struct kref * kref)485144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4866ff5abbfSGustavo F. Padovan {
487144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
488144ad330SSyam Sidhardhan 
4894af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4904af66c69SJaganath Kanakkassery 
491333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
49223691d75SGustavo F. Padovan 	list_del(&chan->global_l);
493333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
49423691d75SGustavo F. Padovan 
4954af66c69SJaganath Kanakkassery 	kfree(chan);
4966ff5abbfSGustavo F. Padovan }
4976ff5abbfSGustavo F. Padovan 
l2cap_chan_hold(struct l2cap_chan * c)49830648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
49930648372SJaganath Kanakkassery {
50093917fd2SKai Ye 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
50130648372SJaganath Kanakkassery 
502144ad330SSyam Sidhardhan 	kref_get(&c->kref);
50330648372SJaganath Kanakkassery }
50430648372SJaganath Kanakkassery 
l2cap_chan_hold_unless_zero(struct l2cap_chan * c)505d0be8347SLuiz Augusto von Dentz struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
506d0be8347SLuiz Augusto von Dentz {
507d0be8347SLuiz Augusto von Dentz 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
508d0be8347SLuiz Augusto von Dentz 
509d0be8347SLuiz Augusto von Dentz 	if (!kref_get_unless_zero(&c->kref))
510d0be8347SLuiz Augusto von Dentz 		return NULL;
511d0be8347SLuiz Augusto von Dentz 
512d0be8347SLuiz Augusto von Dentz 	return c;
513d0be8347SLuiz Augusto von Dentz }
514d0be8347SLuiz Augusto von Dentz 
l2cap_chan_put(struct l2cap_chan * c)51530648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
51630648372SJaganath Kanakkassery {
51793917fd2SKai Ye 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
51830648372SJaganath Kanakkassery 
519144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
52030648372SJaganath Kanakkassery }
5216b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
52230648372SJaganath Kanakkassery 
l2cap_chan_set_defaults(struct l2cap_chan * chan)523bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
524bd4b1653SAndrei Emeltchenko {
525bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
526bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
527bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
528bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5296a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5306a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
531c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
532bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5336a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5346a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5356a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5363a9d54b1SArchie Pusaka 
5376a5e8165SJukka Rissanen 	chan->conf_state = 0;
5383a9d54b1SArchie Pusaka 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
539bd4b1653SAndrei Emeltchenko 
540bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
541bd4b1653SAndrei Emeltchenko }
5426b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
543bd4b1653SAndrei Emeltchenko 
l2cap_le_rx_credits(struct l2cap_chan * chan)544e2310343SSebastian Urban static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan)
545e2310343SSebastian Urban {
546e2310343SSebastian Urban 	size_t sdu_len = chan->sdu ? chan->sdu->len : 0;
547e2310343SSebastian Urban 
548e2310343SSebastian Urban 	if (chan->mps == 0)
549e2310343SSebastian Urban 		return 0;
550e2310343SSebastian Urban 
551e2310343SSebastian Urban 	/* If we don't know the available space in the receiver buffer, give
552e2310343SSebastian Urban 	 * enough credits for a full packet.
553e2310343SSebastian Urban 	 */
554e2310343SSebastian Urban 	if (chan->rx_avail == -1)
555e2310343SSebastian Urban 		return (chan->imtu / chan->mps) + 1;
556e2310343SSebastian Urban 
557e2310343SSebastian Urban 	/* If we know how much space is available in the receive buffer, give
558e2310343SSebastian Urban 	 * out as many credits as would fill the buffer.
559e2310343SSebastian Urban 	 */
560e2310343SSebastian Urban 	if (chan->rx_avail <= sdu_len)
561e2310343SSebastian Urban 		return 0;
562e2310343SSebastian Urban 
563e2310343SSebastian Urban 	return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps);
564e2310343SSebastian Urban }
565e2310343SSebastian Urban 
l2cap_le_flowctl_init(struct l2cap_chan * chan,u16 tx_credits)566ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
56738319713SJohan Hedberg {
5680ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5690ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5700ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
571ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
572fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
573fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
574e2310343SSebastian Urban 	chan->rx_credits = l2cap_le_rx_credits(chan);
5750ce43ce6SJohan Hedberg 
5760ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
57738319713SJohan Hedberg }
57838319713SJohan Hedberg 
l2cap_ecred_init(struct l2cap_chan * chan,u16 tx_credits)57915f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
58015f02b91SLuiz Augusto von Dentz {
58115f02b91SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, tx_credits);
58215f02b91SLuiz Augusto von Dentz 
58315f02b91SLuiz Augusto von Dentz 	/* L2CAP implementations shall support a minimum MPS of 64 octets */
58415f02b91SLuiz Augusto von Dentz 	if (chan->mps < L2CAP_ECRED_MIN_MPS) {
58515f02b91SLuiz Augusto von Dentz 		chan->mps = L2CAP_ECRED_MIN_MPS;
586e2310343SSebastian Urban 		chan->rx_credits = l2cap_le_rx_credits(chan);
58715f02b91SLuiz Augusto von Dentz 	}
58815f02b91SLuiz Augusto von Dentz }
58915f02b91SLuiz Augusto von Dentz 
__l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)59093c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5910a708f8fSGustavo F. Padovan {
5920a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
593097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5940a708f8fSGustavo F. Padovan 
5959f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5960a708f8fSGustavo F. Padovan 
5978c1d787bSGustavo F. Padovan 	chan->conn = conn;
5980a708f8fSGustavo F. Padovan 
5995491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
6005491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
6010a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
602fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
60321626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
6040c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
6055491120eSAndrei Emeltchenko 		break;
6065491120eSAndrei Emeltchenko 
6075491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
6080a708f8fSGustavo F. Padovan 		/* Connectionless socket */
609fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
610fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
6110c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
6125491120eSAndrei Emeltchenko 		break;
6135491120eSAndrei Emeltchenko 
6142338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
6152338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
616416fa752SAndrei Emeltchenko 		break;
617416fa752SAndrei Emeltchenko 
6185491120eSAndrei Emeltchenko 	default:
6190a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
620fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
621fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
6220c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
6230a708f8fSGustavo F. Padovan 	}
6240a708f8fSGustavo F. Padovan 
6258f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
6268f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
6278f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
6288f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
6298f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
6308936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
6318f7975b1SAndrei Emeltchenko 
632371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
633baa7e1faSGustavo F. Padovan 
634c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
635c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
636c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
6375ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
6385ee9891dSJohan Hedberg 
6393df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
640643162a8SAndrei Emeltchenko }
641643162a8SAndrei Emeltchenko 
l2cap_chan_add(struct l2cap_conn * conn,struct l2cap_chan * chan)642466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
643643162a8SAndrei Emeltchenko {
644643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
645643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
6463df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
6470a708f8fSGustavo F. Padovan }
6480a708f8fSGustavo F. Padovan 
l2cap_chan_del(struct l2cap_chan * chan,int err)649466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6500a708f8fSGustavo F. Padovan {
6518c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6520a708f8fSGustavo F. Padovan 
653c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
6540a708f8fSGustavo F. Padovan 
65549d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
65649d11741SJohan Hedberg 	       state_to_string(chan->state));
6570a708f8fSGustavo F. Padovan 
65872847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
65972847ce0SJohan Hedberg 
6600a708f8fSGustavo F. Padovan 	if (conn) {
661baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6623df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6633d57dc68SGustavo F. Padovan 
664371fd835SUlisses Furquim 		l2cap_chan_put(chan);
665baa7e1faSGustavo F. Padovan 
6668c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6673cabbfdaSAndrei Emeltchenko 
668c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
669c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
670c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
671c16900cfSJohan Hedberg 		 */
672c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
673c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
67476a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
675419e08c1SAndrei Emeltchenko 	}
676419e08c1SAndrei Emeltchenko 
6772827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6786ff5abbfSGustavo F. Padovan 		return;
6792ead70b8SGustavo F. Padovan 
680ee556f66SGustavo Padovan 	switch (chan->mode) {
681ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
682ee556f66SGustavo Padovan 		break;
6830a708f8fSGustavo F. Padovan 
68438319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
68515f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
686177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
68738319713SJohan Hedberg 		break;
68838319713SJohan Hedberg 
689ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6901a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6911a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6921a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6930a708f8fSGustavo F. Padovan 
694f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6950a708f8fSGustavo F. Padovan 
6963c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6973c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
69819186c7bSGustavo A. R. Silva 		fallthrough;
699ee556f66SGustavo Padovan 
700ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
701ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
702ee556f66SGustavo Padovan 		break;
7030a708f8fSGustavo F. Padovan 	}
7040a708f8fSGustavo F. Padovan }
7056b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
7060a708f8fSGustavo F. Padovan 
__l2cap_chan_list_id(struct l2cap_conn * conn,u16 id,l2cap_chan_func_t func,void * data)7079aa9d947SLuiz Augusto von Dentz static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
7089aa9d947SLuiz Augusto von Dentz 				 l2cap_chan_func_t func, void *data)
7099aa9d947SLuiz Augusto von Dentz {
7109aa9d947SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *l;
7119aa9d947SLuiz Augusto von Dentz 
7129aa9d947SLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
7139aa9d947SLuiz Augusto von Dentz 		if (chan->ident == id)
7149aa9d947SLuiz Augusto von Dentz 			func(chan, data);
7159aa9d947SLuiz Augusto von Dentz 	}
7169aa9d947SLuiz Augusto von Dentz }
7179aa9d947SLuiz Augusto von Dentz 
__l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)718da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
719da49b602SLuiz Augusto von Dentz 			      void *data)
720da49b602SLuiz Augusto von Dentz {
721da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
722da49b602SLuiz Augusto von Dentz 
723da49b602SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
724da49b602SLuiz Augusto von Dentz 		func(chan, data);
725da49b602SLuiz Augusto von Dentz 	}
726da49b602SLuiz Augusto von Dentz }
727da49b602SLuiz Augusto von Dentz 
l2cap_chan_list(struct l2cap_conn * conn,l2cap_chan_func_t func,void * data)728da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
729da49b602SLuiz Augusto von Dentz 		     void *data)
730da49b602SLuiz Augusto von Dentz {
731da49b602SLuiz Augusto von Dentz 	if (!conn)
732da49b602SLuiz Augusto von Dentz 		return;
733da49b602SLuiz Augusto von Dentz 
734da49b602SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
735da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, func, data);
736da49b602SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
737da49b602SLuiz Augusto von Dentz }
738da49b602SLuiz Augusto von Dentz 
739da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
740da49b602SLuiz Augusto von Dentz 
l2cap_conn_update_id_addr(struct work_struct * work)741f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
742387a33e3SJohan Hedberg {
743f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
744b8b23001SLuiz Augusto von Dentz 					       id_addr_timer.work);
745f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
746387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
747387a33e3SJohan Hedberg 
748387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
749387a33e3SJohan Hedberg 
750387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
751387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
752387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
753a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
754387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
755387a33e3SJohan Hedberg 	}
756387a33e3SJohan Hedberg 
757387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
758387a33e3SJohan Hedberg }
759387a33e3SJohan Hedberg 
l2cap_chan_le_connect_reject(struct l2cap_chan * chan)76027e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
76127e2d4c8SJohan Hedberg {
76227e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
76327e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
76427e2d4c8SJohan Hedberg 	u16 result;
76527e2d4c8SJohan Hedberg 
76627e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
767571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
76827e2d4c8SJohan Hedberg 	else
769571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
77027e2d4c8SJohan Hedberg 
77127e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
77227e2d4c8SJohan Hedberg 
77327e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
77427e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
7753916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
7760cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
77727e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
77827e2d4c8SJohan Hedberg 
77927e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
78027e2d4c8SJohan Hedberg 		       &rsp);
78127e2d4c8SJohan Hedberg }
78227e2d4c8SJohan Hedberg 
l2cap_chan_ecred_connect_reject(struct l2cap_chan * chan)78315f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
78415f02b91SLuiz Augusto von Dentz {
78515f02b91SLuiz Augusto von Dentz 	l2cap_state_change(chan, BT_DISCONN);
78615f02b91SLuiz Augusto von Dentz 
7879aa9d947SLuiz Augusto von Dentz 	__l2cap_ecred_conn_rsp_defer(chan);
78815f02b91SLuiz Augusto von Dentz }
78915f02b91SLuiz Augusto von Dentz 
l2cap_chan_connect_reject(struct l2cap_chan * chan)790791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
791791d60f7SJohan Hedberg {
792791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
793791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
794791d60f7SJohan Hedberg 	u16 result;
795791d60f7SJohan Hedberg 
796791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
797791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
798791d60f7SJohan Hedberg 	else
799791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
800791d60f7SJohan Hedberg 
801791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
802791d60f7SJohan Hedberg 
803791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
804791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
805791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
806dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
807791d60f7SJohan Hedberg 
808791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
809791d60f7SJohan Hedberg }
810791d60f7SJohan Hedberg 
l2cap_chan_close(struct l2cap_chan * chan,int reason)8110f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
8124519de9aSGustavo F. Padovan {
8134519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8144519de9aSGustavo F. Padovan 
8157eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
8164519de9aSGustavo F. Padovan 
81789bc500eSGustavo F. Padovan 	switch (chan->state) {
8184519de9aSGustavo F. Padovan 	case BT_LISTEN:
819c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8204519de9aSGustavo F. Padovan 		break;
8214519de9aSGustavo F. Padovan 
8224519de9aSGustavo F. Padovan 	case BT_CONNECTED:
8234519de9aSGustavo F. Padovan 	case BT_CONFIG:
8247b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8258d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8265e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
8274519de9aSGustavo F. Padovan 		} else
8284519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
8294519de9aSGustavo F. Padovan 		break;
8304519de9aSGustavo F. Padovan 
8314519de9aSGustavo F. Padovan 	case BT_CONNECT2:
832791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
833791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
834791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
83515f02b91SLuiz Augusto von Dentz 			else if (conn->hcon->type == LE_LINK) {
83615f02b91SLuiz Augusto von Dentz 				switch (chan->mode) {
83715f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_LE_FLOWCTL:
83827e2d4c8SJohan Hedberg 					l2cap_chan_le_connect_reject(chan);
83915f02b91SLuiz Augusto von Dentz 					break;
84015f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_EXT_FLOWCTL:
84115f02b91SLuiz Augusto von Dentz 					l2cap_chan_ecred_connect_reject(chan);
8429aa9d947SLuiz Augusto von Dentz 					return;
84315f02b91SLuiz Augusto von Dentz 				}
84415f02b91SLuiz Augusto von Dentz 			}
8454519de9aSGustavo F. Padovan 		}
8464519de9aSGustavo F. Padovan 
8474519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8484519de9aSGustavo F. Padovan 		break;
8494519de9aSGustavo F. Padovan 
8504519de9aSGustavo F. Padovan 	case BT_CONNECT:
8514519de9aSGustavo F. Padovan 	case BT_DISCONN:
8524519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8534519de9aSGustavo F. Padovan 		break;
8544519de9aSGustavo F. Padovan 
8554519de9aSGustavo F. Padovan 	default:
856c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8574519de9aSGustavo F. Padovan 		break;
8584519de9aSGustavo F. Padovan 	}
8594519de9aSGustavo F. Padovan }
8606b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8614519de9aSGustavo F. Padovan 
l2cap_get_auth_type(struct l2cap_chan * chan)8624343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8630a708f8fSGustavo F. Padovan {
8646a974b50SMarcel Holtmann 	switch (chan->chan_type) {
8656a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
8664343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8670a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8687d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8690a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
8700a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8710a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
8720a708f8fSGustavo F. Padovan 		default:
8730a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8740a708f8fSGustavo F. Padovan 		}
8756a974b50SMarcel Holtmann 		break;
8763124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
877dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8783124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
8793124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
8803124b843SMarcel Holtmann 		}
8817d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
8827d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
8833124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
8843124b843SMarcel Holtmann 		else
8853124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
8863124b843SMarcel Holtmann 		break;
8876a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
888dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8894343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
8904343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
8910a708f8fSGustavo F. Padovan 
8927d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
8937d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
8940a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
8950a708f8fSGustavo F. Padovan 			else
8960a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
8976a974b50SMarcel Holtmann 		}
89819186c7bSGustavo A. R. Silva 		fallthrough;
89919186c7bSGustavo A. R. Silva 
9006a974b50SMarcel Holtmann 	default:
9014343478fSGustavo F. Padovan 		switch (chan->sec_level) {
9020a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
9037d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
9040a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
9050a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
9060a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
9070a708f8fSGustavo F. Padovan 		default:
9080a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
9090a708f8fSGustavo F. Padovan 		}
9106a974b50SMarcel Holtmann 		break;
9110a708f8fSGustavo F. Padovan 	}
9120a708f8fSGustavo F. Padovan }
9130a708f8fSGustavo F. Padovan 
9140a708f8fSGustavo F. Padovan /* Service level security */
l2cap_chan_check_security(struct l2cap_chan * chan,bool initiator)915e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
9160a708f8fSGustavo F. Padovan {
9178c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9180a708f8fSGustavo F. Padovan 	__u8 auth_type;
9190a708f8fSGustavo F. Padovan 
920a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
921a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
922a17de2feSJohan Hedberg 
9234343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
9240a708f8fSGustavo F. Padovan 
925e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
926e7cafc45SJohan Hedberg 				 initiator);
9270a708f8fSGustavo F. Padovan }
9280a708f8fSGustavo F. Padovan 
l2cap_get_ident(struct l2cap_conn * conn)929b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9300a708f8fSGustavo F. Padovan {
9310a708f8fSGustavo F. Padovan 	u8 id;
9320a708f8fSGustavo F. Padovan 
9330a708f8fSGustavo F. Padovan 	/* Get next available identificator.
9340a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
9350a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
9360a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
9370a708f8fSGustavo F. Padovan 	 */
9380a708f8fSGustavo F. Padovan 
9395a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
9400a708f8fSGustavo F. Padovan 
9410a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
9420a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
9430a708f8fSGustavo F. Padovan 
9440a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
9450a708f8fSGustavo F. Padovan 
9465a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
9470a708f8fSGustavo F. Padovan 
9480a708f8fSGustavo F. Padovan 	return id;
9490a708f8fSGustavo F. Padovan }
9500a708f8fSGustavo F. Padovan 
l2cap_send_cmd(struct l2cap_conn * conn,u8 ident,u8 code,u16 len,void * data)9512d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9522d792818SGustavo Padovan 			   void *data)
9530a708f8fSGustavo F. Padovan {
9540a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9550a708f8fSGustavo F. Padovan 	u8 flags;
9560a708f8fSGustavo F. Padovan 
9570a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
9580a708f8fSGustavo F. Padovan 
9590a708f8fSGustavo F. Padovan 	if (!skb)
9600a708f8fSGustavo F. Padovan 		return;
9610a708f8fSGustavo F. Padovan 
962f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
963f6af675eSSteven Walter 	 * not support auto-flushing packets) */
964f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
965f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
9660a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
9670a708f8fSGustavo F. Padovan 	else
9680a708f8fSGustavo F. Padovan 		flags = ACL_START;
9690a708f8fSGustavo F. Padovan 
97014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9715e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
97214b12d0bSJaikumar Ganesh 
97373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
9740a708f8fSGustavo F. Padovan }
9750a708f8fSGustavo F. Padovan 
l2cap_do_send(struct l2cap_chan * chan,struct sk_buff * skb)97673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
97773d80debSLuiz Augusto von Dentz {
97873d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
97973d80debSLuiz Augusto von Dentz 	u16 flags;
98073d80debSLuiz Augusto von Dentz 
98173d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
98273d80debSLuiz Augusto von Dentz 	       skb->priority);
98373d80debSLuiz Augusto von Dentz 
984f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
985f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
986f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
987f6af675eSSteven Walter 	 */
988f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
989f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
990f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
99173d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
99273d80debSLuiz Augusto von Dentz 	else
99373d80debSLuiz Augusto von Dentz 		flags = ACL_START;
99473d80debSLuiz Augusto von Dentz 
99573d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
99673d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
9970a708f8fSGustavo F. Padovan }
9980a708f8fSGustavo F. Padovan 
__unpack_enhanced_control(u16 enh,struct l2cap_ctrl * control)999b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
1000b5c6aaedSMat Martineau {
1001b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
1002b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
1003b5c6aaedSMat Martineau 
1004b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
1005b5c6aaedSMat Martineau 		/* S-Frame */
1006b5c6aaedSMat Martineau 		control->sframe = 1;
1007b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1008b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
1009b5c6aaedSMat Martineau 
1010b5c6aaedSMat Martineau 		control->sar = 0;
1011b5c6aaedSMat Martineau 		control->txseq = 0;
1012b5c6aaedSMat Martineau 	} else {
1013b5c6aaedSMat Martineau 		/* I-Frame */
1014b5c6aaedSMat Martineau 		control->sframe = 0;
1015b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1016b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
1017b5c6aaedSMat Martineau 
1018b5c6aaedSMat Martineau 		control->poll = 0;
1019b5c6aaedSMat Martineau 		control->super = 0;
1020b5c6aaedSMat Martineau 	}
1021b5c6aaedSMat Martineau }
1022b5c6aaedSMat Martineau 
__unpack_extended_control(u32 ext,struct l2cap_ctrl * control)1023b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1024b5c6aaedSMat Martineau {
1025b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1026b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1027b5c6aaedSMat Martineau 
1028b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1029b5c6aaedSMat Martineau 		/* S-Frame */
1030b5c6aaedSMat Martineau 		control->sframe = 1;
1031b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1032b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1033b5c6aaedSMat Martineau 
1034b5c6aaedSMat Martineau 		control->sar = 0;
1035b5c6aaedSMat Martineau 		control->txseq = 0;
1036b5c6aaedSMat Martineau 	} else {
1037b5c6aaedSMat Martineau 		/* I-Frame */
1038b5c6aaedSMat Martineau 		control->sframe = 0;
1039b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1040b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1041b5c6aaedSMat Martineau 
1042b5c6aaedSMat Martineau 		control->poll = 0;
1043b5c6aaedSMat Martineau 		control->super = 0;
1044b5c6aaedSMat Martineau 	}
1045b5c6aaedSMat Martineau }
1046b5c6aaedSMat Martineau 
__unpack_control(struct l2cap_chan * chan,struct sk_buff * skb)1047b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1048b5c6aaedSMat Martineau 				    struct sk_buff *skb)
1049b5c6aaedSMat Martineau {
1050b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1051b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
1052a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1053cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1054b5c6aaedSMat Martineau 	} else {
1055b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
1056a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1057cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1058b5c6aaedSMat Martineau 	}
1059b5c6aaedSMat Martineau }
1060b5c6aaedSMat Martineau 
__pack_extended_control(struct l2cap_ctrl * control)1061b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1062b5c6aaedSMat Martineau {
1063b5c6aaedSMat Martineau 	u32 packed;
1064b5c6aaedSMat Martineau 
1065b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1066b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1067b5c6aaedSMat Martineau 
1068b5c6aaedSMat Martineau 	if (control->sframe) {
1069b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1070b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1071b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1072b5c6aaedSMat Martineau 	} else {
1073b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
1074b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1075b5c6aaedSMat Martineau 	}
1076b5c6aaedSMat Martineau 
1077b5c6aaedSMat Martineau 	return packed;
1078b5c6aaedSMat Martineau }
1079b5c6aaedSMat Martineau 
__pack_enhanced_control(struct l2cap_ctrl * control)1080b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1081b5c6aaedSMat Martineau {
1082b5c6aaedSMat Martineau 	u16 packed;
1083b5c6aaedSMat Martineau 
1084b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1085b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1086b5c6aaedSMat Martineau 
1087b5c6aaedSMat Martineau 	if (control->sframe) {
1088b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1089b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1090b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1091b5c6aaedSMat Martineau 	} else {
1092b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1093b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1094b5c6aaedSMat Martineau 	}
1095b5c6aaedSMat Martineau 
1096b5c6aaedSMat Martineau 	return packed;
1097b5c6aaedSMat Martineau }
1098b5c6aaedSMat Martineau 
__pack_control(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)1099b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1100b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1101b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1102b5c6aaedSMat Martineau {
1103b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1104b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1105b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1106b5c6aaedSMat Martineau 	} else {
1107b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1108b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1109b5c6aaedSMat Martineau 	}
1110b5c6aaedSMat Martineau }
1111b5c6aaedSMat Martineau 
__ertm_hdr_size(struct l2cap_chan * chan)1112ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1113ba7aa64fSGustavo Padovan {
1114ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1115ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1116ba7aa64fSGustavo Padovan 	else
1117ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1118ba7aa64fSGustavo Padovan }
1119ba7aa64fSGustavo Padovan 
l2cap_create_sframe_pdu(struct l2cap_chan * chan,u32 control)1120a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1121a67d7f6fSMat Martineau 					       u32 control)
11220a708f8fSGustavo F. Padovan {
11230a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
11240a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1125ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
11260a708f8fSGustavo F. Padovan 
11270a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
112803a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
11290a708f8fSGustavo F. Padovan 
1130a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
11310a708f8fSGustavo F. Padovan 
11320a708f8fSGustavo F. Padovan 	if (!skb)
1133a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
11340a708f8fSGustavo F. Padovan 
11354df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
11360a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1137fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
113888843ab0SAndrei Emeltchenko 
1139a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1140a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1141a67d7f6fSMat Martineau 	else
1142a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11430a708f8fSGustavo F. Padovan 
114447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1145a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
114603a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
11470a708f8fSGustavo F. Padovan 	}
11480a708f8fSGustavo F. Padovan 
114973d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1150a67d7f6fSMat Martineau 	return skb;
1151a67d7f6fSMat Martineau }
1152a67d7f6fSMat Martineau 
l2cap_send_sframe(struct l2cap_chan * chan,struct l2cap_ctrl * control)1153a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1154a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1155a67d7f6fSMat Martineau {
1156a67d7f6fSMat Martineau 	struct sk_buff *skb;
1157a67d7f6fSMat Martineau 	u32 control_field;
1158a67d7f6fSMat Martineau 
1159a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1160a67d7f6fSMat Martineau 
1161a67d7f6fSMat Martineau 	if (!control->sframe)
1162a67d7f6fSMat Martineau 		return;
1163a67d7f6fSMat Martineau 
1164a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1165a67d7f6fSMat Martineau 	    !control->poll)
1166a67d7f6fSMat Martineau 		control->final = 1;
1167a67d7f6fSMat Martineau 
1168a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1169a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1170a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1171a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1172a67d7f6fSMat Martineau 
1173a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1174a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1175a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1176a67d7f6fSMat Martineau 	}
1177a67d7f6fSMat Martineau 
1178a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1179a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1180a67d7f6fSMat Martineau 
1181a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1182a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1183a67d7f6fSMat Martineau 	else
1184a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1185a67d7f6fSMat Martineau 
1186a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1187a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
118873d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
11890a708f8fSGustavo F. Padovan }
11900a708f8fSGustavo F. Padovan 
l2cap_send_rr_or_rnr(struct l2cap_chan * chan,bool poll)1191c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11920a708f8fSGustavo F. Padovan {
1193c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
11940a708f8fSGustavo F. Padovan 
1195c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1196c9e3d5e0SMat Martineau 
1197c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1198c9e3d5e0SMat Martineau 	control.sframe = 1;
1199c9e3d5e0SMat Martineau 	control.poll = poll;
1200c9e3d5e0SMat Martineau 
1201c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1202c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1203c9e3d5e0SMat Martineau 	else
1204c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1205c9e3d5e0SMat Martineau 
1206c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1207c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
12080a708f8fSGustavo F. Padovan }
12090a708f8fSGustavo F. Padovan 
__l2cap_no_conn_pending(struct l2cap_chan * chan)1210b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12110a708f8fSGustavo F. Padovan {
12125ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12135ff6f34dSJohan Hedberg 		return true;
12145ff6f34dSJohan Hedberg 
1215c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12160a708f8fSGustavo F. Padovan }
12170a708f8fSGustavo F. Padovan 
l2cap_send_conn_req(struct l2cap_chan * chan)12182766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12199b27f350SAndrei Emeltchenko {
12209b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12219b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
12229b27f350SAndrei Emeltchenko 
12239b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
12249b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
12259b27f350SAndrei Emeltchenko 
12269b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
12279b27f350SAndrei Emeltchenko 
12289b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12299b27f350SAndrei Emeltchenko 
12309b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12319b27f350SAndrei Emeltchenko }
12329b27f350SAndrei Emeltchenko 
l2cap_chan_ready(struct l2cap_chan * chan)12339f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12349f0caeb1SVinicius Costa Gomes {
1235315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1236315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1237315917e0SJohan Hedberg 	 * procedure is complete.
1238315917e0SJohan Hedberg 	 */
1239315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1240315917e0SJohan Hedberg 		return;
1241315917e0SJohan Hedberg 
12422827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12439f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12449f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12459f0caeb1SVinicius Costa Gomes 
124615f02b91SLuiz Augusto von Dentz 	switch (chan->mode) {
124715f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_LE_FLOWCTL:
124815f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
124915f02b91SLuiz Augusto von Dentz 		if (!chan->tx_credits)
12500ce43ce6SJohan Hedberg 			chan->ops->suspend(chan);
125115f02b91SLuiz Augusto von Dentz 		break;
125215f02b91SLuiz Augusto von Dentz 	}
1253177f8f2bSJohan Hedberg 
125454a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12559f0caeb1SVinicius Costa Gomes 
125654a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12579f0caeb1SVinicius Costa Gomes }
12589f0caeb1SVinicius Costa Gomes 
l2cap_le_connect(struct l2cap_chan * chan)1259f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1260f1496deeSJohan Hedberg {
1261f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1262f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1263f1496deeSJohan Hedberg 
1264595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1265595177f3SJohan Hedberg 		return;
1266595177f3SJohan Hedberg 
12674b6e228eSLuiz Augusto von Dentz 	if (!chan->imtu)
12684b6e228eSLuiz Augusto von Dentz 		chan->imtu = chan->conn->mtu;
12694b6e228eSLuiz Augusto von Dentz 
1270ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1271fe149310SLuiz Augusto von Dentz 
1272a5133fe8SXiaohui Zhang 	memset(&req, 0, sizeof(req));
1273f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1274f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1275f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
12763916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
12770cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1278f1496deeSJohan Hedberg 
1279f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1280f1496deeSJohan Hedberg 
1281f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1282f1496deeSJohan Hedberg 		       sizeof(req), &req);
1283f1496deeSJohan Hedberg }
1284f1496deeSJohan Hedberg 
1285da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
128615f02b91SLuiz Augusto von Dentz 	struct {
128715f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_req req;
1288da49b602SLuiz Augusto von Dentz 		__le16 scid[5];
128915f02b91SLuiz Augusto von Dentz 	} __packed pdu;
1290da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
1291da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1292da49b602SLuiz Augusto von Dentz 	int count;
1293da49b602SLuiz Augusto von Dentz };
1294da49b602SLuiz Augusto von Dentz 
l2cap_ecred_defer_connect(struct l2cap_chan * chan,void * data)1295da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1296da49b602SLuiz Augusto von Dentz {
1297da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data *conn = data;
1298da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1299da49b602SLuiz Augusto von Dentz 
1300da49b602SLuiz Augusto von Dentz 	if (chan == conn->chan)
1301da49b602SLuiz Augusto von Dentz 		return;
1302da49b602SLuiz Augusto von Dentz 
1303da49b602SLuiz Augusto von Dentz 	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1304da49b602SLuiz Augusto von Dentz 		return;
1305da49b602SLuiz Augusto von Dentz 
1306da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
1307da49b602SLuiz Augusto von Dentz 
1308da49b602SLuiz Augusto von Dentz 	/* Only add deferred channels with the same PID/PSM */
1309da49b602SLuiz Augusto von Dentz 	if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1310da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1311da49b602SLuiz Augusto von Dentz 		return;
131215f02b91SLuiz Augusto von Dentz 
131315f02b91SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
131415f02b91SLuiz Augusto von Dentz 		return;
131515f02b91SLuiz Augusto von Dentz 
131615f02b91SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
131715f02b91SLuiz Augusto von Dentz 
1318da49b602SLuiz Augusto von Dentz 	/* Set the same ident so we can match on the rsp */
1319da49b602SLuiz Augusto von Dentz 	chan->ident = conn->chan->ident;
1320da49b602SLuiz Augusto von Dentz 
1321da49b602SLuiz Augusto von Dentz 	/* Include all channels deferred */
1322da49b602SLuiz Augusto von Dentz 	conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1323da49b602SLuiz Augusto von Dentz 
1324da49b602SLuiz Augusto von Dentz 	conn->count++;
1325da49b602SLuiz Augusto von Dentz }
1326da49b602SLuiz Augusto von Dentz 
l2cap_ecred_connect(struct l2cap_chan * chan)1327da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1328da49b602SLuiz Augusto von Dentz {
1329da49b602SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
1330da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data data;
1331da49b602SLuiz Augusto von Dentz 
1332da49b602SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1333da49b602SLuiz Augusto von Dentz 		return;
1334da49b602SLuiz Augusto von Dentz 
1335da49b602SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1336da49b602SLuiz Augusto von Dentz 		return;
1337da49b602SLuiz Augusto von Dentz 
1338da49b602SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
1339da49b602SLuiz Augusto von Dentz 
1340d3715b23SMinghao Chi (CGEL ZTE) 	memset(&data, 0, sizeof(data));
1341da49b602SLuiz Augusto von Dentz 	data.pdu.req.psm     = chan->psm;
1342da49b602SLuiz Augusto von Dentz 	data.pdu.req.mtu     = cpu_to_le16(chan->imtu);
1343da49b602SLuiz Augusto von Dentz 	data.pdu.req.mps     = cpu_to_le16(chan->mps);
1344da49b602SLuiz Augusto von Dentz 	data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1345da49b602SLuiz Augusto von Dentz 	data.pdu.scid[0]     = cpu_to_le16(chan->scid);
134615f02b91SLuiz Augusto von Dentz 
134715f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
1348da49b602SLuiz Augusto von Dentz 
1349da49b602SLuiz Augusto von Dentz 	data.count = 1;
1350da49b602SLuiz Augusto von Dentz 	data.chan = chan;
1351da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1352da49b602SLuiz Augusto von Dentz 
1353da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
135415f02b91SLuiz Augusto von Dentz 
135515f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1356da49b602SLuiz Augusto von Dentz 		       sizeof(data.pdu.req) + data.count * sizeof(__le16),
1357da49b602SLuiz Augusto von Dentz 		       &data.pdu);
135815f02b91SLuiz Augusto von Dentz }
135915f02b91SLuiz Augusto von Dentz 
l2cap_le_start(struct l2cap_chan * chan)1360f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1361f1496deeSJohan Hedberg {
1362f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1363f1496deeSJohan Hedberg 
1364f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1365f1496deeSJohan Hedberg 		return;
1366f1496deeSJohan Hedberg 
1367f1496deeSJohan Hedberg 	if (!chan->psm) {
1368f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1369f1496deeSJohan Hedberg 		return;
1370f1496deeSJohan Hedberg 	}
1371f1496deeSJohan Hedberg 
137215f02b91SLuiz Augusto von Dentz 	if (chan->state == BT_CONNECT) {
137315f02b91SLuiz Augusto von Dentz 		if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
137415f02b91SLuiz Augusto von Dentz 			l2cap_ecred_connect(chan);
137515f02b91SLuiz Augusto von Dentz 		else
1376f1496deeSJohan Hedberg 			l2cap_le_connect(chan);
1377f1496deeSJohan Hedberg 	}
137815f02b91SLuiz Augusto von Dentz }
1379f1496deeSJohan Hedberg 
l2cap_start_connection(struct l2cap_chan * chan)138093c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
138193c3e8f5SAndrei Emeltchenko {
1382cd5d26a9SLuiz Augusto von Dentz 	if (chan->conn->hcon->type == LE_LINK) {
1383f1496deeSJohan Hedberg 		l2cap_le_start(chan);
138493c3e8f5SAndrei Emeltchenko 	} else {
138593c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
138693c3e8f5SAndrei Emeltchenko 	}
138793c3e8f5SAndrei Emeltchenko }
138893c3e8f5SAndrei Emeltchenko 
l2cap_request_info(struct l2cap_conn * conn)1389aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
13900a708f8fSGustavo F. Padovan {
13910a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1392aeaeb4bbSJohan Hedberg 
1393aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1394aeaeb4bbSJohan Hedberg 		return;
1395aeaeb4bbSJohan Hedberg 
1396dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
13970a708f8fSGustavo F. Padovan 
13980a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
13990a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
14000a708f8fSGustavo F. Padovan 
1401ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
14020a708f8fSGustavo F. Padovan 
14032d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
14042d792818SGustavo Padovan 		       sizeof(req), &req);
14050a708f8fSGustavo F. Padovan }
1406aeaeb4bbSJohan Hedberg 
l2cap_check_enc_key_size(struct hci_conn * hcon)1407693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1408693cd8ceSMarcel Holtmann {
1409693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1410693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1411693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1412693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1413693cd8ceSMarcel Holtmann 	 *
1414693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1415693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1416693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1417693cd8ceSMarcel Holtmann 	 */
1418288c0697SArchie Pusaka 	int min_key_size = hcon->hdev->min_enc_key_size;
1419288c0697SArchie Pusaka 
1420288c0697SArchie Pusaka 	/* On FIPS security level, key size must be 16 bytes */
1421288c0697SArchie Pusaka 	if (hcon->sec_level == BT_SECURITY_FIPS)
1422288c0697SArchie Pusaka 		min_key_size = 16;
1423288c0697SArchie Pusaka 
1424693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1425288c0697SArchie Pusaka 		hcon->enc_key_size >= min_key_size);
1426693cd8ceSMarcel Holtmann }
1427693cd8ceSMarcel Holtmann 
l2cap_do_start(struct l2cap_chan * chan)1428aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1429aeaeb4bbSJohan Hedberg {
1430aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1431aeaeb4bbSJohan Hedberg 
1432aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1433aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1434aeaeb4bbSJohan Hedberg 		return;
1435aeaeb4bbSJohan Hedberg 	}
1436aeaeb4bbSJohan Hedberg 
1437aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1438aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1439aeaeb4bbSJohan Hedberg 		return;
1440aeaeb4bbSJohan Hedberg 	}
1441aeaeb4bbSJohan Hedberg 
1442aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1443aeaeb4bbSJohan Hedberg 		return;
1444aeaeb4bbSJohan Hedberg 
1445693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1446693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1447693cd8ceSMarcel Holtmann 		return;
1448693cd8ceSMarcel Holtmann 
1449693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1450aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1451693cd8ceSMarcel Holtmann 	else
1452693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
14530a708f8fSGustavo F. Padovan }
14540a708f8fSGustavo F. Padovan 
l2cap_mode_supported(__u8 mode,__u32 feat_mask)14550a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
14560a708f8fSGustavo F. Padovan {
14570a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
14580a708f8fSGustavo F. Padovan 	if (!disable_ertm)
14590a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
14600a708f8fSGustavo F. Padovan 
14610a708f8fSGustavo F. Padovan 	switch (mode) {
14620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
14630a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
14640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
14650a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
14660a708f8fSGustavo F. Padovan 	default:
14670a708f8fSGustavo F. Padovan 		return 0x00;
14680a708f8fSGustavo F. Padovan 	}
14690a708f8fSGustavo F. Padovan }
14700a708f8fSGustavo F. Padovan 
l2cap_send_disconn_req(struct l2cap_chan * chan,int err)14715e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
14720a708f8fSGustavo F. Padovan {
14735e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
14740a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
14750a708f8fSGustavo F. Padovan 
14760a708f8fSGustavo F. Padovan 	if (!conn)
14770a708f8fSGustavo F. Padovan 		return;
14780a708f8fSGustavo F. Padovan 
1479aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
14801a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
14811a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
14821a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
14830a708f8fSGustavo F. Padovan 	}
14840a708f8fSGustavo F. Padovan 
1485fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1486fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
14872d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
14882d792818SGustavo Padovan 		       sizeof(req), &req);
14890a708f8fSGustavo F. Padovan 
1490f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
14910a708f8fSGustavo F. Padovan }
14920a708f8fSGustavo F. Padovan 
14930a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
l2cap_conn_start(struct l2cap_conn * conn)14940a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
14950a708f8fSGustavo F. Padovan {
14963df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
14970a708f8fSGustavo F. Padovan 
14980a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
14990a708f8fSGustavo F. Padovan 
15003df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15010a708f8fSGustavo F. Padovan 
15023df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
15036be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15040a708f8fSGustavo F. Padovan 
1505715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1506aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
15076be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
15080a708f8fSGustavo F. Padovan 			continue;
15090a708f8fSGustavo F. Padovan 		}
15100a708f8fSGustavo F. Padovan 
151189bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1512e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1513b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
15146be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
15150a708f8fSGustavo F. Padovan 				continue;
15160a708f8fSGustavo F. Padovan 			}
15170a708f8fSGustavo F. Padovan 
1518c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1519c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1520c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
15210f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
15226be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
15230a708f8fSGustavo F. Padovan 				continue;
15240a708f8fSGustavo F. Padovan 			}
15250a708f8fSGustavo F. Padovan 
1526693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
152793c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1528693cd8ceSMarcel Holtmann 			else
1529693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
15300a708f8fSGustavo F. Padovan 
153189bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
15320a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
15330a708f8fSGustavo F. Padovan 			char buf[128];
1534fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1535fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
15360a708f8fSGustavo F. Padovan 
1537e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1538bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1539dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1540dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
15412dc4e510SGustavo Padovan 					chan->ops->defer(chan);
15420a708f8fSGustavo F. Padovan 
15430a708f8fSGustavo F. Padovan 				} else {
1544acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1545dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1546dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
15470a708f8fSGustavo F. Padovan 				}
15480a708f8fSGustavo F. Padovan 			} else {
1549dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1550dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
15510a708f8fSGustavo F. Padovan 			}
15520a708f8fSGustavo F. Padovan 
1553fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1554fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
15550a708f8fSGustavo F. Padovan 
1556c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
15570a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
15586be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
15590a708f8fSGustavo F. Padovan 				continue;
15600a708f8fSGustavo F. Padovan 			}
15610a708f8fSGustavo F. Padovan 
1562c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
15630a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1564e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
156573ffa904SGustavo F. Padovan 			chan->num_conf_req++;
15660a708f8fSGustavo F. Padovan 		}
15670a708f8fSGustavo F. Padovan 
15686be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15690a708f8fSGustavo F. Padovan 	}
15700a708f8fSGustavo F. Padovan 
15713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15720a708f8fSGustavo F. Padovan }
15730a708f8fSGustavo F. Padovan 
l2cap_le_conn_ready(struct l2cap_conn * conn)1574b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1575b62f328bSVille Tervo {
1576cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1577dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1578b62f328bSVille Tervo 
1579e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1580b62f328bSVille Tervo 
1581e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1582e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1583e760ec12SJohan Hedberg 	 */
1584e760ec12SJohan Hedberg 	if (hcon->out)
1585e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1586cc8dba2bSMarcel Holtmann 
158774be523cSArchie Pusaka 	/* For LE peripheral connections, make sure the connection interval
15885153ceb9SBhaskar Chowdhury 	 * is in the range of the minimum and maximum interval that has
158980afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
159080afeb6cSMarcel Holtmann 	 * the connection update procedure.
159180afeb6cSMarcel Holtmann 	 */
159240bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
159380afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
159480afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
159580afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
159680afeb6cSMarcel Holtmann 
159780afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
159880afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
159980afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
160080afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
160180afeb6cSMarcel Holtmann 
160280afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
160380afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
160480afeb6cSMarcel Holtmann 	}
1605b62f328bSVille Tervo }
1606b62f328bSVille Tervo 
l2cap_conn_ready(struct l2cap_conn * conn)16070a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
16080a708f8fSGustavo F. Padovan {
160948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1610cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
16110a708f8fSGustavo F. Padovan 
16120a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
16130a708f8fSGustavo F. Padovan 
1614aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1615aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1616aeaeb4bbSJohan Hedberg 
1617e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1618e760ec12SJohan Hedberg 
16193df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1620baa7e1faSGustavo F. Padovan 
16216be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16220a708f8fSGustavo F. Padovan 
1623cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1624f1496deeSJohan Hedberg 			l2cap_le_start(chan);
162563128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1626aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
162774e75740SGustavo Padovan 				l2cap_chan_ready(chan);
16281c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1629fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
16301c244f79SGustavo Padovan 		}
16310a708f8fSGustavo F. Padovan 
16326be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16330a708f8fSGustavo F. Padovan 	}
16340a708f8fSGustavo F. Padovan 
16353df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
163661a939c6SJohan Hedberg 
163779a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
163879a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
163979a05727SJohan Hedberg 
164061a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
16410a708f8fSGustavo F. Padovan }
16420a708f8fSGustavo F. Padovan 
16430a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
l2cap_conn_unreliable(struct l2cap_conn * conn,int err)16440a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
16450a708f8fSGustavo F. Padovan {
164648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
16470a708f8fSGustavo F. Padovan 
16480a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
16490a708f8fSGustavo F. Padovan 
16503df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16510a708f8fSGustavo F. Padovan 
16523df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1653ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
16541d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
16550a708f8fSGustavo F. Padovan 	}
16560a708f8fSGustavo F. Padovan 
16573df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16580a708f8fSGustavo F. Padovan }
16590a708f8fSGustavo F. Padovan 
l2cap_info_timeout(struct work_struct * work)1660f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
16610a708f8fSGustavo F. Padovan {
1662f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1663030013d8SGustavo F. Padovan 					       info_timer.work);
16640a708f8fSGustavo F. Padovan 
16650a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
16660a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
16670a708f8fSGustavo F. Padovan 
16680a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
16690a708f8fSGustavo F. Padovan }
16700a708f8fSGustavo F. Padovan 
16712c8e1411SDavid Herrmann /*
16722c8e1411SDavid Herrmann  * l2cap_user
16732c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
16742c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
16752c8e1411SDavid Herrmann  * during unregistration.
16762c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
16772c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
16782c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16792c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
16802c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16812c8e1411SDavid Herrmann  * any time if they don't.
16822c8e1411SDavid Herrmann  */
16832c8e1411SDavid Herrmann 
l2cap_register_user(struct l2cap_conn * conn,struct l2cap_user * user)16842c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16852c8e1411SDavid Herrmann {
16862c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16872c8e1411SDavid Herrmann 	int ret;
16882c8e1411SDavid Herrmann 
16892c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
16902c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
16912c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16922c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
16932c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
16942c8e1411SDavid Herrmann 	 * here, too. */
16952c8e1411SDavid Herrmann 
16962c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16972c8e1411SDavid Herrmann 
1698835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
16992c8e1411SDavid Herrmann 		ret = -EINVAL;
17002c8e1411SDavid Herrmann 		goto out_unlock;
17012c8e1411SDavid Herrmann 	}
17022c8e1411SDavid Herrmann 
17032c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
17042c8e1411SDavid Herrmann 	if (!conn->hchan) {
17052c8e1411SDavid Herrmann 		ret = -ENODEV;
17062c8e1411SDavid Herrmann 		goto out_unlock;
17072c8e1411SDavid Herrmann 	}
17082c8e1411SDavid Herrmann 
17092c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
17102c8e1411SDavid Herrmann 	if (ret)
17112c8e1411SDavid Herrmann 		goto out_unlock;
17122c8e1411SDavid Herrmann 
17132c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
17142c8e1411SDavid Herrmann 	ret = 0;
17152c8e1411SDavid Herrmann 
17162c8e1411SDavid Herrmann out_unlock:
17172c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
17182c8e1411SDavid Herrmann 	return ret;
17192c8e1411SDavid Herrmann }
17202c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
17212c8e1411SDavid Herrmann 
l2cap_unregister_user(struct l2cap_conn * conn,struct l2cap_user * user)17222c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
17232c8e1411SDavid Herrmann {
17242c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
17252c8e1411SDavid Herrmann 
17262c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
17272c8e1411SDavid Herrmann 
1728835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
17292c8e1411SDavid Herrmann 		goto out_unlock;
17302c8e1411SDavid Herrmann 
1731ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
17322c8e1411SDavid Herrmann 	user->remove(conn, user);
17332c8e1411SDavid Herrmann 
17342c8e1411SDavid Herrmann out_unlock:
17352c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
17362c8e1411SDavid Herrmann }
17372c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
17382c8e1411SDavid Herrmann 
l2cap_unregister_all_users(struct l2cap_conn * conn)17392c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
17402c8e1411SDavid Herrmann {
17412c8e1411SDavid Herrmann 	struct l2cap_user *user;
17422c8e1411SDavid Herrmann 
17432c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
17442c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1745ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
17462c8e1411SDavid Herrmann 		user->remove(conn, user);
17472c8e1411SDavid Herrmann 	}
17482c8e1411SDavid Herrmann }
17492c8e1411SDavid Herrmann 
l2cap_conn_del(struct hci_conn * hcon,int err)17505d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
17515d3de7dfSVinicius Costa Gomes {
17525d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
17535d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
17545d3de7dfSVinicius Costa Gomes 
17555d3de7dfSVinicius Costa Gomes 	if (!conn)
17565d3de7dfSVinicius Costa Gomes 		return;
17575d3de7dfSVinicius Costa Gomes 
17585d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
17595d3de7dfSVinicius Costa Gomes 
17605d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
17615d3de7dfSVinicius Costa Gomes 
176261a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
17637ab56c3aSJukka Taimisto 
17647ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
17657ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
17667ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
17677ab56c3aSJukka Taimisto 	 */
17687ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
17697ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
177061a939c6SJohan Hedberg 
1771b8b23001SLuiz Augusto von Dentz 	cancel_delayed_work_sync(&conn->id_addr_timer);
1772f3d82d0cSJohan Hedberg 
17732c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
17742c8e1411SDavid Herrmann 
1775e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1776e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1777e31fb860SJohan Hedberg 
17783df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17793df91ea2SAndrei Emeltchenko 
17805d3de7dfSVinicius Costa Gomes 	/* Kill channels */
17815d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
178261d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
17836be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17846be36555SAndrei Emeltchenko 
17855d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
17866be36555SAndrei Emeltchenko 
178780b98027SGustavo Padovan 		chan->ops->close(chan);
17886c08fc89SManish Mandlik 
17896c08fc89SManish Mandlik 		l2cap_chan_unlock(chan);
179061d6ef3eSMat Martineau 		l2cap_chan_put(chan);
17915d3de7dfSVinicius Costa Gomes 	}
17925d3de7dfSVinicius Costa Gomes 
17933df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17943df91ea2SAndrei Emeltchenko 
179573d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
179673d80debSLuiz Augusto von Dentz 
17975d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1798127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
17995d3de7dfSVinicius Costa Gomes 
18005d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
18019c903e37SDavid Herrmann 	conn->hchan = NULL;
18029c903e37SDavid Herrmann 	l2cap_conn_put(conn);
18035d3de7dfSVinicius Costa Gomes }
18045d3de7dfSVinicius Costa Gomes 
l2cap_conn_free(struct kref * ref)18059c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
18069c903e37SDavid Herrmann {
18079c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
18089c903e37SDavid Herrmann 
18099c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
18109c903e37SDavid Herrmann 	kfree(conn);
18119c903e37SDavid Herrmann }
18129c903e37SDavid Herrmann 
l2cap_conn_get(struct l2cap_conn * conn)181351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
18149c903e37SDavid Herrmann {
18159c903e37SDavid Herrmann 	kref_get(&conn->ref);
181651bb8457SJohan Hedberg 	return conn;
18179c903e37SDavid Herrmann }
18189c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
18199c903e37SDavid Herrmann 
l2cap_conn_put(struct l2cap_conn * conn)18209c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
18219c903e37SDavid Herrmann {
18229c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
18239c903e37SDavid Herrmann }
18249c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
18259c903e37SDavid Herrmann 
18260a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
18270a708f8fSGustavo F. Padovan 
1828c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
18290a708f8fSGustavo F. Padovan  * Returns closest match.
18300a708f8fSGustavo F. Padovan  */
l2cap_global_chan_by_psm(int state,__le16 psm,bdaddr_t * src,bdaddr_t * dst,u8 link_type)1831c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1832c2287681SIdo Yariv 						   bdaddr_t *src,
1833bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1834bf20fd4eSJohan Hedberg 						   u8 link_type)
18350a708f8fSGustavo F. Padovan {
1836332f1795SLuiz Augusto von Dentz 	struct l2cap_chan *c, *tmp, *c1 = NULL;
18370a708f8fSGustavo F. Padovan 
183823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
18390a708f8fSGustavo F. Padovan 
1840332f1795SLuiz Augusto von Dentz 	list_for_each_entry_safe(c, tmp, &chan_list, global_l) {
184189bc500eSGustavo F. Padovan 		if (state && c->state != state)
18420a708f8fSGustavo F. Padovan 			continue;
18430a708f8fSGustavo F. Padovan 
1844bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1845bf20fd4eSJohan Hedberg 			continue;
1846bf20fd4eSJohan Hedberg 
1847bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1848bf20fd4eSJohan Hedberg 			continue;
1849bf20fd4eSJohan Hedberg 
1850f937b758SLuiz Augusto von Dentz 		if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) {
1851c2287681SIdo Yariv 			int src_match, dst_match;
1852c2287681SIdo Yariv 			int src_any, dst_any;
1853c2287681SIdo Yariv 
18540a708f8fSGustavo F. Padovan 			/* Exact match. */
18557eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18567eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1857c2287681SIdo Yariv 			if (src_match && dst_match) {
1858fc5ae5b4SLuiz Augusto von Dentz 				if (!l2cap_chan_hold_unless_zero(c))
1859fc5ae5b4SLuiz Augusto von Dentz 					continue;
1860fc5ae5b4SLuiz Augusto von Dentz 
1861a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
186223691d75SGustavo F. Padovan 				return c;
186323691d75SGustavo F. Padovan 			}
18640a708f8fSGustavo F. Padovan 
18650a708f8fSGustavo F. Padovan 			/* Closest match */
18667eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18677eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1868c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1869c2287681SIdo Yariv 			    (src_any && dst_any))
187023691d75SGustavo F. Padovan 				c1 = c;
18710a708f8fSGustavo F. Padovan 		}
18720a708f8fSGustavo F. Padovan 	}
18730a708f8fSGustavo F. Padovan 
1874a24cce14SJohan Hedberg 	if (c1)
1875d0be8347SLuiz Augusto von Dentz 		c1 = l2cap_chan_hold_unless_zero(c1);
1876a24cce14SJohan Hedberg 
187723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18780a708f8fSGustavo F. Padovan 
187923691d75SGustavo F. Padovan 	return c1;
18800a708f8fSGustavo F. Padovan }
18810a708f8fSGustavo F. Padovan 
l2cap_monitor_timeout(struct work_struct * work)1882721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
18830a708f8fSGustavo F. Padovan {
1884721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1885721c4181SGustavo F. Padovan 					       monitor_timer.work);
18860a708f8fSGustavo F. Padovan 
1887525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
18880a708f8fSGustavo F. Padovan 
18896be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
18906be36555SAndrei Emeltchenko 
189180909e04SMat Martineau 	if (!chan->conn) {
18926be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
18938d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
18940a708f8fSGustavo F. Padovan 		return;
18950a708f8fSGustavo F. Padovan 	}
18960a708f8fSGustavo F. Padovan 
1897401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
18980a708f8fSGustavo F. Padovan 
18996be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
19008d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
19010a708f8fSGustavo F. Padovan }
19020a708f8fSGustavo F. Padovan 
l2cap_retrans_timeout(struct work_struct * work)1903721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
19040a708f8fSGustavo F. Padovan {
1905721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1906721c4181SGustavo F. Padovan 					       retrans_timer.work);
19070a708f8fSGustavo F. Padovan 
190849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
19090a708f8fSGustavo F. Padovan 
19106be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
19116be36555SAndrei Emeltchenko 
191280909e04SMat Martineau 	if (!chan->conn) {
191380909e04SMat Martineau 		l2cap_chan_unlock(chan);
191480909e04SMat Martineau 		l2cap_chan_put(chan);
191580909e04SMat Martineau 		return;
191680909e04SMat Martineau 	}
19170a708f8fSGustavo F. Padovan 
1918401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
19196be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
19208d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
19210a708f8fSGustavo F. Padovan }
19220a708f8fSGustavo F. Padovan 
l2cap_streaming_send(struct l2cap_chan * chan,struct sk_buff_head * skbs)1923d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
19243733937dSMat Martineau 				 struct sk_buff_head *skbs)
19250a708f8fSGustavo F. Padovan {
19260a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
19273733937dSMat Martineau 	struct l2cap_ctrl *control;
19280a708f8fSGustavo F. Padovan 
19293733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
19303733937dSMat Martineau 
19313733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
19323733937dSMat Martineau 
19333733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
19343733937dSMat Martineau 
19353733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
19363733937dSMat Martineau 
1937a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1938a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
19393733937dSMat Martineau 
19403733937dSMat Martineau 		control->reqseq = 0;
19413733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
19423733937dSMat Martineau 
19433733937dSMat Martineau 		__pack_control(chan, control, skb);
19440a708f8fSGustavo F. Padovan 
194547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
19463733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
19473733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19480a708f8fSGustavo F. Padovan 		}
19490a708f8fSGustavo F. Padovan 
19504343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
19510a708f8fSGustavo F. Padovan 
1952b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
19533733937dSMat Martineau 
1954836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
19553733937dSMat Martineau 		chan->frames_sent++;
19560a708f8fSGustavo F. Padovan 	}
19570a708f8fSGustavo F. Padovan }
19580a708f8fSGustavo F. Padovan 
l2cap_ertm_send(struct l2cap_chan * chan)195967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
19600a708f8fSGustavo F. Padovan {
19610a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
196218a48e76SMat Martineau 	struct l2cap_ctrl *control;
196318a48e76SMat Martineau 	int sent = 0;
196418a48e76SMat Martineau 
196518a48e76SMat Martineau 	BT_DBG("chan %p", chan);
19660a708f8fSGustavo F. Padovan 
196789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
19680a708f8fSGustavo F. Padovan 		return -ENOTCONN;
19690a708f8fSGustavo F. Padovan 
197094122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
197194122bbeSMat Martineau 		return 0;
197294122bbeSMat Martineau 
197318a48e76SMat Martineau 	while (chan->tx_send_head &&
197418a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
197518a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
19760a708f8fSGustavo F. Padovan 
197718a48e76SMat Martineau 		skb = chan->tx_send_head;
19780a708f8fSGustavo F. Padovan 
1979a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
1980a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
19810a708f8fSGustavo F. Padovan 
1982e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
198318a48e76SMat Martineau 			control->final = 1;
1984e2ab4353SGustavo F. Padovan 
198518a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
198618a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
198718a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
19880a708f8fSGustavo F. Padovan 
198918a48e76SMat Martineau 		__pack_control(chan, control, skb);
19900a708f8fSGustavo F. Padovan 
199147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
199218a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
199318a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
19940a708f8fSGustavo F. Padovan 		}
19950a708f8fSGustavo F. Padovan 
199618a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
199718a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
199818a48e76SMat Martineau 		 */
199918a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
200018a48e76SMat Martineau 
200118a48e76SMat Martineau 		if (!tx_skb)
200218a48e76SMat Martineau 			break;
20030a708f8fSGustavo F. Padovan 
20041a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
20050a708f8fSGustavo F. Padovan 
2006836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20076a026610SGustavo F. Padovan 		chan->unacked_frames++;
20086a026610SGustavo F. Padovan 		chan->frames_sent++;
200918a48e76SMat Martineau 		sent++;
20100a708f8fSGustavo F. Padovan 
201158d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
201258d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
20130a708f8fSGustavo F. Padovan 		else
201458d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
201518a48e76SMat Martineau 
201618a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2017b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20180a708f8fSGustavo F. Padovan 	}
20190a708f8fSGustavo F. Padovan 
2020b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2021b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
202218a48e76SMat Martineau 
202318a48e76SMat Martineau 	return sent;
20240a708f8fSGustavo F. Padovan }
20250a708f8fSGustavo F. Padovan 
l2cap_ertm_resend(struct l2cap_chan * chan)2026e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2027e1fbd4c1SMat Martineau {
2028e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2029e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2030e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2031e1fbd4c1SMat Martineau 	u16 seq;
2032e1fbd4c1SMat Martineau 
2033e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2034e1fbd4c1SMat Martineau 
2035e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2036e1fbd4c1SMat Martineau 		return;
2037e1fbd4c1SMat Martineau 
2038e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2039e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2040e1fbd4c1SMat Martineau 
2041e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2042e1fbd4c1SMat Martineau 		if (!skb) {
2043e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2044e1fbd4c1SMat Martineau 			       seq);
2045e1fbd4c1SMat Martineau 			continue;
2046e1fbd4c1SMat Martineau 		}
2047e1fbd4c1SMat Martineau 
2048a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
2049a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
2050e1fbd4c1SMat Martineau 
2051e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2052a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2053e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
20545e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2055e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2056e1fbd4c1SMat Martineau 			break;
2057e1fbd4c1SMat Martineau 		}
2058e1fbd4c1SMat Martineau 
2059e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2060e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2061e1fbd4c1SMat Martineau 			control.final = 1;
2062e1fbd4c1SMat Martineau 		else
2063e1fbd4c1SMat Martineau 			control.final = 0;
2064e1fbd4c1SMat Martineau 
2065e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2066e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2067e1fbd4c1SMat Martineau 			 * writeable copy
2068e1fbd4c1SMat Martineau 			 */
20698bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2070e1fbd4c1SMat Martineau 		} else {
20718bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2072e1fbd4c1SMat Martineau 		}
2073e1fbd4c1SMat Martineau 
2074e1fbd4c1SMat Martineau 		if (!tx_skb) {
2075e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2076e1fbd4c1SMat Martineau 			break;
2077e1fbd4c1SMat Martineau 		}
2078e1fbd4c1SMat Martineau 
2079e1fbd4c1SMat Martineau 		/* Update skb contents */
2080e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2081e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2082e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2083e1fbd4c1SMat Martineau 		} else {
2084e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2085e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2086e1fbd4c1SMat Martineau 		}
2087e1fbd4c1SMat Martineau 
208813cac152SLukasz Rymanowski 		/* Update FCS */
2089e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
209013cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
209113cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
209213cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
209313cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2094e1fbd4c1SMat Martineau 		}
2095e1fbd4c1SMat Martineau 
2096e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2097e1fbd4c1SMat Martineau 
2098e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2099e1fbd4c1SMat Martineau 
2100e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2101e1fbd4c1SMat Martineau 	}
2102e1fbd4c1SMat Martineau }
2103e1fbd4c1SMat Martineau 
l2cap_retransmit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2104f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2105f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2106f80842a8SMat Martineau {
2107f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2108f80842a8SMat Martineau 
2109f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2110f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2111f80842a8SMat Martineau }
2112f80842a8SMat Martineau 
l2cap_retransmit_all(struct l2cap_chan * chan,struct l2cap_ctrl * control)2113d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2114d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2115d2a7ac5dSMat Martineau {
2116e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2117e1fbd4c1SMat Martineau 
2118e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2119e1fbd4c1SMat Martineau 
2120e1fbd4c1SMat Martineau 	if (control->poll)
2121e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2122e1fbd4c1SMat Martineau 
2123e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2124e1fbd4c1SMat Martineau 
2125e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2126e1fbd4c1SMat Martineau 		return;
2127e1fbd4c1SMat Martineau 
2128e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2129e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2130a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2131e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2132e1fbd4c1SMat Martineau 				break;
2133e1fbd4c1SMat Martineau 		}
2134e1fbd4c1SMat Martineau 
2135e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2136e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2137e1fbd4c1SMat Martineau 				break;
2138e1fbd4c1SMat Martineau 
2139e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2140a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2141e1fbd4c1SMat Martineau 		}
2142e1fbd4c1SMat Martineau 
2143e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2144e1fbd4c1SMat Martineau 	}
2145d2a7ac5dSMat Martineau }
2146d2a7ac5dSMat Martineau 
l2cap_send_ack(struct l2cap_chan * chan)2147b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2148b17e73bbSSzymon Janc {
21490a0aba42SMat Martineau 	struct l2cap_ctrl control;
21500a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
21510a0aba42SMat Martineau 					 chan->last_acked_seq);
21520a0aba42SMat Martineau 	int threshold;
21530a0aba42SMat Martineau 
21540a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
21550a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
21560a0aba42SMat Martineau 
21570a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
21580a0aba42SMat Martineau 	control.sframe = 1;
21590a0aba42SMat Martineau 
21600a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
21610a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2162b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
21630a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
21640a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
21650a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
21660a0aba42SMat Martineau 	} else {
21670a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
21680a0aba42SMat Martineau 			l2cap_ertm_send(chan);
21690a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
21700a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
21710a0aba42SMat Martineau 				frames_to_ack = 0;
21720a0aba42SMat Martineau 		}
21730a0aba42SMat Martineau 
2174c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
21750a0aba42SMat Martineau 		 * Calculate without mul or div
21760a0aba42SMat Martineau 		 */
2177c20f8e35SMat Martineau 		threshold = chan->ack_win;
21780a0aba42SMat Martineau 		threshold += threshold << 1;
21790a0aba42SMat Martineau 		threshold >>= 2;
21800a0aba42SMat Martineau 
2181b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
21820a0aba42SMat Martineau 		       threshold);
21830a0aba42SMat Martineau 
21840a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
21850a0aba42SMat Martineau 			__clear_ack_timer(chan);
21860a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
21870a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
21880a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
21890a0aba42SMat Martineau 			frames_to_ack = 0;
21900a0aba42SMat Martineau 		}
21910a0aba42SMat Martineau 
21920a0aba42SMat Martineau 		if (frames_to_ack)
21930a0aba42SMat Martineau 			__set_ack_timer(chan);
21940a0aba42SMat Martineau 	}
2195b17e73bbSSzymon Janc }
2196b17e73bbSSzymon Janc 
l2cap_skbuff_fromiovec(struct l2cap_chan * chan,struct msghdr * msg,int len,int count,struct sk_buff * skb)219704124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
219804124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
219904124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
22000a708f8fSGustavo F. Padovan {
22010952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
22020a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
220390338947SGustavo Padovan 	int sent = 0;
22040a708f8fSGustavo F. Padovan 
2205cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
22060a708f8fSGustavo F. Padovan 		return -EFAULT;
22070a708f8fSGustavo F. Padovan 
22080a708f8fSGustavo F. Padovan 	sent += count;
22090a708f8fSGustavo F. Padovan 	len  -= count;
22100a708f8fSGustavo F. Padovan 
22110a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
22120a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
22130a708f8fSGustavo F. Padovan 	while (len) {
2214fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2215fbe00700SGustavo Padovan 
22160a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
22170a708f8fSGustavo F. Padovan 
2218d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
221990338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2220fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2221fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
22222f7719ceSAndrei Emeltchenko 
2223fbe00700SGustavo Padovan 		*frag = tmp;
2224fbe00700SGustavo Padovan 
2225cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2226cbbd26b8SAl Viro 				   &msg->msg_iter))
22270a708f8fSGustavo F. Padovan 			return -EFAULT;
22280a708f8fSGustavo F. Padovan 
22290a708f8fSGustavo F. Padovan 		sent += count;
22300a708f8fSGustavo F. Padovan 		len  -= count;
22310a708f8fSGustavo F. Padovan 
22322d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
22332d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
22342d0ed3d5SGustavo Padovan 
22350a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
22360a708f8fSGustavo F. Padovan 	}
22370a708f8fSGustavo F. Padovan 
22380a708f8fSGustavo F. Padovan 	return sent;
22390a708f8fSGustavo F. Padovan }
22400a708f8fSGustavo F. Padovan 
l2cap_create_connless_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22415e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
22428d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
22430a708f8fSGustavo F. Padovan {
22448c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22450a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
224603a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
22470a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22480a708f8fSGustavo F. Padovan 
22498d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
22508d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
22510a708f8fSGustavo F. Padovan 
22520a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
22532f7719ceSAndrei Emeltchenko 
2254d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
225590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
225690338947SGustavo Padovan 	if (IS_ERR(skb))
225790338947SGustavo Padovan 		return skb;
22580a708f8fSGustavo F. Padovan 
22590a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22604df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2261fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2262daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
226343b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
22640a708f8fSGustavo F. Padovan 
22650952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22660a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22670a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22680a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22690a708f8fSGustavo F. Padovan 	}
22700a708f8fSGustavo F. Padovan 	return skb;
22710a708f8fSGustavo F. Padovan }
22720a708f8fSGustavo F. Padovan 
l2cap_create_basic_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len)22735e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
22748d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
22750a708f8fSGustavo F. Padovan {
22768c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
22770a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2278f2ba7faeSGustavo Padovan 	int err, count;
22790a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
22800a708f8fSGustavo F. Padovan 
2281b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
22820a708f8fSGustavo F. Padovan 
2283f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
22842f7719ceSAndrei Emeltchenko 
2285d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
228690338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
228790338947SGustavo Padovan 	if (IS_ERR(skb))
228890338947SGustavo Padovan 		return skb;
22890a708f8fSGustavo F. Padovan 
22900a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
22914df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2292fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
22936ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
22940a708f8fSGustavo F. Padovan 
22950952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
22960a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
22970a708f8fSGustavo F. Padovan 		kfree_skb(skb);
22980a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
22990a708f8fSGustavo F. Padovan 	}
23000a708f8fSGustavo F. Padovan 	return skb;
23010a708f8fSGustavo F. Padovan }
23020a708f8fSGustavo F. Padovan 
l2cap_create_iframe_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2303ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2304ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
230594122bbeSMat Martineau 					       u16 sdulen)
23060a708f8fSGustavo F. Padovan {
23078c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23080a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2309e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
23100a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23110a708f8fSGustavo F. Padovan 
2312b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
23130a708f8fSGustavo F. Padovan 
23140a708f8fSGustavo F. Padovan 	if (!conn)
23150a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
23160a708f8fSGustavo F. Padovan 
2317ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2318e4ca6d98SAndrei Emeltchenko 
23190a708f8fSGustavo F. Padovan 	if (sdulen)
232003a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
23210a708f8fSGustavo F. Padovan 
232247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
232303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
23240a708f8fSGustavo F. Padovan 
23250a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23262f7719ceSAndrei Emeltchenko 
2327d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
232890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
232990338947SGustavo Padovan 	if (IS_ERR(skb))
233090338947SGustavo Padovan 		return skb;
23310a708f8fSGustavo F. Padovan 
23320a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23334df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2334fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
23350a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
233688843ab0SAndrei Emeltchenko 
233718a48e76SMat Martineau 	/* Control header is populated later */
233818a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
233918a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
234018a48e76SMat Martineau 	else
234118a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
234288843ab0SAndrei Emeltchenko 
23430a708f8fSGustavo F. Padovan 	if (sdulen)
234403a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
23450a708f8fSGustavo F. Padovan 
23460952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23470a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23480a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23490a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23500a708f8fSGustavo F. Padovan 	}
23510a708f8fSGustavo F. Padovan 
2352a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2353a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
23540a708f8fSGustavo F. Padovan 	return skb;
23550a708f8fSGustavo F. Padovan }
23560a708f8fSGustavo F. Padovan 
l2cap_segment_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)235794122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
235894122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
235994122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
23600a708f8fSGustavo F. Padovan {
23610a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
236294122bbeSMat Martineau 	u16 sdu_len;
236394122bbeSMat Martineau 	size_t pdu_len;
236494122bbeSMat Martineau 	u8 sar;
23650a708f8fSGustavo F. Padovan 
2366b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
23670a708f8fSGustavo F. Padovan 
236894122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
236994122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
237094122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
237194122bbeSMat Martineau 	 */
237294122bbeSMat Martineau 
237394122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
237494122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
237594122bbeSMat Martineau 
2376a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
237794122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
237894122bbeSMat Martineau 
237994122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
238035d401dfSGustavo Padovan 	if (chan->fcs)
238135d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
238235d401dfSGustavo Padovan 
2383ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
238494122bbeSMat Martineau 
238594122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
238694122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
238794122bbeSMat Martineau 
238894122bbeSMat Martineau 	if (len <= pdu_len) {
238994122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
239094122bbeSMat Martineau 		sdu_len = 0;
239194122bbeSMat Martineau 		pdu_len = len;
239294122bbeSMat Martineau 	} else {
239394122bbeSMat Martineau 		sar = L2CAP_SAR_START;
239494122bbeSMat Martineau 		sdu_len = len;
239594122bbeSMat Martineau 	}
23960a708f8fSGustavo F. Padovan 
23970a708f8fSGustavo F. Padovan 	while (len > 0) {
239894122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
23990a708f8fSGustavo F. Padovan 
24000a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
240194122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
24020a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
24030a708f8fSGustavo F. Padovan 		}
24040a708f8fSGustavo F. Padovan 
2405a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
240694122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
24070a708f8fSGustavo F. Padovan 
240894122bbeSMat Martineau 		len -= pdu_len;
2409069cb270SLukasz Rymanowski 		if (sdu_len)
241094122bbeSMat Martineau 			sdu_len = 0;
241194122bbeSMat Martineau 
241294122bbeSMat Martineau 		if (len <= pdu_len) {
241394122bbeSMat Martineau 			sar = L2CAP_SAR_END;
241494122bbeSMat Martineau 			pdu_len = len;
241594122bbeSMat Martineau 		} else {
241694122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
241794122bbeSMat Martineau 		}
241894122bbeSMat Martineau 	}
241994122bbeSMat Martineau 
2420f0f62799SGustavo Padovan 	return 0;
24210a708f8fSGustavo F. Padovan }
24220a708f8fSGustavo F. Padovan 
l2cap_create_le_flowctl_pdu(struct l2cap_chan * chan,struct msghdr * msg,size_t len,u16 sdulen)2423177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2424177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2425177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2426177f8f2bSJohan Hedberg {
2427177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2428177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2429177f8f2bSJohan Hedberg 	int err, count, hlen;
2430177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2431177f8f2bSJohan Hedberg 
2432177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2433177f8f2bSJohan Hedberg 
2434177f8f2bSJohan Hedberg 	if (!conn)
2435177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2436177f8f2bSJohan Hedberg 
2437177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2438177f8f2bSJohan Hedberg 
2439177f8f2bSJohan Hedberg 	if (sdulen)
2440177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2441177f8f2bSJohan Hedberg 
2442177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2443177f8f2bSJohan Hedberg 
2444d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2445177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2446177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2447177f8f2bSJohan Hedberg 		return skb;
2448177f8f2bSJohan Hedberg 
2449177f8f2bSJohan Hedberg 	/* Create L2CAP header */
24504df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2451177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2452177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2453177f8f2bSJohan Hedberg 
2454177f8f2bSJohan Hedberg 	if (sdulen)
2455177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2456177f8f2bSJohan Hedberg 
2457177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2458177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2459177f8f2bSJohan Hedberg 		kfree_skb(skb);
2460177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2461177f8f2bSJohan Hedberg 	}
2462177f8f2bSJohan Hedberg 
2463177f8f2bSJohan Hedberg 	return skb;
2464177f8f2bSJohan Hedberg }
2465177f8f2bSJohan Hedberg 
l2cap_segment_le_sdu(struct l2cap_chan * chan,struct sk_buff_head * seg_queue,struct msghdr * msg,size_t len)2466177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2467177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2468177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2469177f8f2bSJohan Hedberg {
2470177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2471177f8f2bSJohan Hedberg 	size_t pdu_len;
2472177f8f2bSJohan Hedberg 	u16 sdu_len;
2473177f8f2bSJohan Hedberg 
2474177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2475177f8f2bSJohan Hedberg 
2476177f8f2bSJohan Hedberg 	sdu_len = len;
247772c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2478177f8f2bSJohan Hedberg 
2479177f8f2bSJohan Hedberg 	while (len > 0) {
2480177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2481177f8f2bSJohan Hedberg 			pdu_len = len;
2482177f8f2bSJohan Hedberg 
2483177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2484177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2485177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2486177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2487177f8f2bSJohan Hedberg 		}
2488177f8f2bSJohan Hedberg 
2489177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2490177f8f2bSJohan Hedberg 
2491177f8f2bSJohan Hedberg 		len -= pdu_len;
2492177f8f2bSJohan Hedberg 
2493177f8f2bSJohan Hedberg 		if (sdu_len) {
2494177f8f2bSJohan Hedberg 			sdu_len = 0;
2495177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2496177f8f2bSJohan Hedberg 		}
2497177f8f2bSJohan Hedberg 	}
2498177f8f2bSJohan Hedberg 
2499177f8f2bSJohan Hedberg 	return 0;
2500177f8f2bSJohan Hedberg }
2501177f8f2bSJohan Hedberg 
l2cap_le_flowctl_send(struct l2cap_chan * chan)25028a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
25038a505b7fSLuiz Augusto von Dentz {
25048a505b7fSLuiz Augusto von Dentz 	int sent = 0;
25058a505b7fSLuiz Augusto von Dentz 
25068a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
25078a505b7fSLuiz Augusto von Dentz 
25088a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
25098a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
25108a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
25118a505b7fSLuiz Augusto von Dentz 		sent++;
25128a505b7fSLuiz Augusto von Dentz 	}
25138a505b7fSLuiz Augusto von Dentz 
25148a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
25158a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
25168a505b7fSLuiz Augusto von Dentz }
25178a505b7fSLuiz Augusto von Dentz 
l2cap_chan_send(struct l2cap_chan * chan,struct msghdr * msg,size_t len)25188d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
25199a91a04aSGustavo F. Padovan {
25209a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
25219a91a04aSGustavo F. Padovan 	int err;
252294122bbeSMat Martineau 	struct sk_buff_head seg_queue;
25239a91a04aSGustavo F. Padovan 
252431e8ce80SSeung-Woo Kim 	if (!chan->conn)
252531e8ce80SSeung-Woo Kim 		return -ENOTCONN;
252631e8ce80SSeung-Woo Kim 
25279a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2528715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
25298d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
25309a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25319a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25329a91a04aSGustavo F. Padovan 
25339a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25349a91a04aSGustavo F. Padovan 		return len;
25359a91a04aSGustavo F. Padovan 	}
25369a91a04aSGustavo F. Padovan 
25379a91a04aSGustavo F. Padovan 	switch (chan->mode) {
253838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
253915f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
2540177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2541177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2542177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2543177f8f2bSJohan Hedberg 
2544177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2545177f8f2bSJohan Hedberg 
2546177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2547177f8f2bSJohan Hedberg 
2548177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2549177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2550177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2551177f8f2bSJohan Hedberg 		}
2552177f8f2bSJohan Hedberg 
2553177f8f2bSJohan Hedberg 		if (err)
2554177f8f2bSJohan Hedberg 			return err;
2555177f8f2bSJohan Hedberg 
2556177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2557177f8f2bSJohan Hedberg 
25588a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2559177f8f2bSJohan Hedberg 
2560177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2561177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2562177f8f2bSJohan Hedberg 
2563177f8f2bSJohan Hedberg 		err = len;
2564177f8f2bSJohan Hedberg 
2565177f8f2bSJohan Hedberg 		break;
2566177f8f2bSJohan Hedberg 
2567fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
25689a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
25699a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
25709a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
25719a91a04aSGustavo F. Padovan 
25729a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
25738d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
25749a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
25759a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
25769a91a04aSGustavo F. Padovan 
25779a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
25789a91a04aSGustavo F. Padovan 		err = len;
25799a91a04aSGustavo F. Padovan 		break;
25809a91a04aSGustavo F. Padovan 
25819a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
25829a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
258394122bbeSMat Martineau 		/* Check outgoing MTU */
258494122bbeSMat Martineau 		if (len > chan->omtu) {
258594122bbeSMat Martineau 			err = -EMSGSIZE;
25869a91a04aSGustavo F. Padovan 			break;
25879a91a04aSGustavo F. Padovan 		}
25889a91a04aSGustavo F. Padovan 
258994122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
259094122bbeSMat Martineau 
259194122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
259294122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
259394122bbeSMat Martineau 		 * allocation.
259494122bbeSMat Martineau 		 */
259594122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
259694122bbeSMat Martineau 
259794122bbeSMat Martineau 		if (err)
259894122bbeSMat Martineau 			break;
259994122bbeSMat Martineau 
26003733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2601d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
26023733937dSMat Martineau 		else
2603d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
260494122bbeSMat Martineau 
26059a91a04aSGustavo F. Padovan 		err = len;
26069a91a04aSGustavo F. Padovan 
260794122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
260894122bbeSMat Martineau 		 * seg_queue and need to be purged.
260994122bbeSMat Martineau 		 */
261094122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
26119a91a04aSGustavo F. Padovan 		break;
26129a91a04aSGustavo F. Padovan 
26139a91a04aSGustavo F. Padovan 	default:
26149a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
26159a91a04aSGustavo F. Padovan 		err = -EBADFD;
26169a91a04aSGustavo F. Padovan 	}
26179a91a04aSGustavo F. Padovan 
26189a91a04aSGustavo F. Padovan 	return err;
26199a91a04aSGustavo F. Padovan }
26206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
26219a91a04aSGustavo F. Padovan 
l2cap_send_srej(struct l2cap_chan * chan,u16 txseq)2622d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2623d2a7ac5dSMat Martineau {
2624bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2625bed68bdeSMat Martineau 	u16 seq;
2626bed68bdeSMat Martineau 
2627b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2628bed68bdeSMat Martineau 
2629bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2630bed68bdeSMat Martineau 	control.sframe = 1;
2631bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2632bed68bdeSMat Martineau 
2633bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2634bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2635bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2636bed68bdeSMat Martineau 			control.reqseq = seq;
2637bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2638bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2639bed68bdeSMat Martineau 		}
2640bed68bdeSMat Martineau 	}
2641bed68bdeSMat Martineau 
2642bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2643d2a7ac5dSMat Martineau }
2644d2a7ac5dSMat Martineau 
l2cap_send_srej_tail(struct l2cap_chan * chan)2645d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2646d2a7ac5dSMat Martineau {
2647bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2648bed68bdeSMat Martineau 
2649bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2650bed68bdeSMat Martineau 
2651bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2652bed68bdeSMat Martineau 		return;
2653bed68bdeSMat Martineau 
2654bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2655bed68bdeSMat Martineau 	control.sframe = 1;
2656bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2657bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2658bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2659d2a7ac5dSMat Martineau }
2660d2a7ac5dSMat Martineau 
l2cap_send_srej_list(struct l2cap_chan * chan,u16 txseq)2661d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2662d2a7ac5dSMat Martineau {
2663bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2664bed68bdeSMat Martineau 	u16 initial_head;
2665bed68bdeSMat Martineau 	u16 seq;
2666bed68bdeSMat Martineau 
2667b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2668bed68bdeSMat Martineau 
2669bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2670bed68bdeSMat Martineau 	control.sframe = 1;
2671bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2672bed68bdeSMat Martineau 
2673bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2674bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2675bed68bdeSMat Martineau 
2676bed68bdeSMat Martineau 	do {
2677bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2678bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2679bed68bdeSMat Martineau 			break;
2680bed68bdeSMat Martineau 
2681bed68bdeSMat Martineau 		control.reqseq = seq;
2682bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2683bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2684bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2685d2a7ac5dSMat Martineau }
2686d2a7ac5dSMat Martineau 
l2cap_process_reqseq(struct l2cap_chan * chan,u16 reqseq)2687608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2688608bcc6dSMat Martineau {
2689608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2690608bcc6dSMat Martineau 	u16 ackseq;
2691608bcc6dSMat Martineau 
2692b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2693608bcc6dSMat Martineau 
2694608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2695608bcc6dSMat Martineau 		return;
2696608bcc6dSMat Martineau 
2697b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2698608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2699608bcc6dSMat Martineau 
2700608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2701608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2702608bcc6dSMat Martineau 
2703608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2704608bcc6dSMat Martineau 		if (acked_skb) {
2705608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2706608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2707608bcc6dSMat Martineau 			chan->unacked_frames--;
2708608bcc6dSMat Martineau 		}
2709608bcc6dSMat Martineau 	}
2710608bcc6dSMat Martineau 
2711608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2712608bcc6dSMat Martineau 
2713608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2714608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2715608bcc6dSMat Martineau 
2716b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2717608bcc6dSMat Martineau }
2718608bcc6dSMat Martineau 
l2cap_abort_rx_srej_sent(struct l2cap_chan * chan)2719608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2720608bcc6dSMat Martineau {
2721608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2722608bcc6dSMat Martineau 
2723608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2724608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2725608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2726608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2727608bcc6dSMat Martineau }
2728608bcc6dSMat Martineau 
l2cap_tx_state_xmit(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2729d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2730608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2731608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2732608bcc6dSMat Martineau {
2733608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2734608bcc6dSMat Martineau 	       event);
2735608bcc6dSMat Martineau 
2736608bcc6dSMat Martineau 	switch (event) {
2737608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2738608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2739608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2740608bcc6dSMat Martineau 
2741608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2742608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2743608bcc6dSMat Martineau 		break;
2744608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2745608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2746608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2747608bcc6dSMat Martineau 
2748608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2749608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2750608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2751608bcc6dSMat Martineau 			 */
2752608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2753608bcc6dSMat Martineau 		}
2754608bcc6dSMat Martineau 
2755608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2756608bcc6dSMat Martineau 
2757608bcc6dSMat Martineau 		break;
2758608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2759608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2760608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2761608bcc6dSMat Martineau 
2762608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2763608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2764608bcc6dSMat Martineau 
2765608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2766608bcc6dSMat Martineau 			local_control.sframe = 1;
2767608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2768608bcc6dSMat Martineau 			local_control.poll = 1;
2769608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2770a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2771608bcc6dSMat Martineau 
2772608bcc6dSMat Martineau 			chan->retry_count = 1;
2773608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2774608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2775608bcc6dSMat Martineau 		}
2776608bcc6dSMat Martineau 		break;
2777608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2778608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2779608bcc6dSMat Martineau 		break;
2780608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2781608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2782608bcc6dSMat Martineau 		chan->retry_count = 1;
2783608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2784608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2785608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2786608bcc6dSMat Martineau 		break;
2787608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2788608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2789608bcc6dSMat Martineau 		chan->retry_count = 1;
2790608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2791608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2792608bcc6dSMat Martineau 		break;
2793608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2794608bcc6dSMat Martineau 		/* Nothing to process */
2795608bcc6dSMat Martineau 		break;
2796608bcc6dSMat Martineau 	default:
2797608bcc6dSMat Martineau 		break;
2798608bcc6dSMat Martineau 	}
2799608bcc6dSMat Martineau }
2800608bcc6dSMat Martineau 
l2cap_tx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2801d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2802608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2803608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2804608bcc6dSMat Martineau {
2805608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2806608bcc6dSMat Martineau 	       event);
2807608bcc6dSMat Martineau 
2808608bcc6dSMat Martineau 	switch (event) {
2809608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2810608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2811608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2812608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2813608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2814608bcc6dSMat Martineau 		break;
2815608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2816608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2817608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2818608bcc6dSMat Martineau 
2819608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2820608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2821608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2822608bcc6dSMat Martineau 			 */
2823608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2824608bcc6dSMat Martineau 		}
2825608bcc6dSMat Martineau 
2826608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2827608bcc6dSMat Martineau 
2828608bcc6dSMat Martineau 		break;
2829608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2830608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2831608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2832608bcc6dSMat Martineau 
2833608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2834608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2835608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2836608bcc6dSMat Martineau 			local_control.sframe = 1;
2837608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2838608bcc6dSMat Martineau 			local_control.poll = 1;
2839608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2840a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2841608bcc6dSMat Martineau 
2842608bcc6dSMat Martineau 			chan->retry_count = 1;
2843608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2844608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2845608bcc6dSMat Martineau 		}
2846608bcc6dSMat Martineau 		break;
2847608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2848608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
284919186c7bSGustavo A. R. Silva 		fallthrough;
2850608bcc6dSMat Martineau 
2851608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2852608bcc6dSMat Martineau 		if (control && control->final) {
2853608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2854608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2855608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2856608bcc6dSMat Martineau 			chan->retry_count = 0;
2857608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2858608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2859608bcc6dSMat Martineau 		}
2860608bcc6dSMat Martineau 		break;
2861608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2862608bcc6dSMat Martineau 		/* Ignore */
2863608bcc6dSMat Martineau 		break;
2864608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2865608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2866608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2867608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2868608bcc6dSMat Martineau 			chan->retry_count++;
2869608bcc6dSMat Martineau 		} else {
28705e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
2871608bcc6dSMat Martineau 		}
2872608bcc6dSMat Martineau 		break;
2873608bcc6dSMat Martineau 	default:
2874608bcc6dSMat Martineau 		break;
2875608bcc6dSMat Martineau 	}
2876608bcc6dSMat Martineau }
2877608bcc6dSMat Martineau 
l2cap_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff_head * skbs,u8 event)2878d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2879608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2880608bcc6dSMat Martineau {
2881608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2882608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2883608bcc6dSMat Martineau 
2884608bcc6dSMat Martineau 	switch (chan->tx_state) {
2885608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2886d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2887608bcc6dSMat Martineau 		break;
2888608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2889d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2890608bcc6dSMat Martineau 		break;
2891608bcc6dSMat Martineau 	default:
2892608bcc6dSMat Martineau 		/* Ignore event */
2893608bcc6dSMat Martineau 		break;
2894608bcc6dSMat Martineau 	}
2895608bcc6dSMat Martineau }
2896608bcc6dSMat Martineau 
l2cap_pass_to_tx(struct l2cap_chan * chan,struct l2cap_ctrl * control)28974b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
28984b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
28994b51dae9SMat Martineau {
29004b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2901401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
29024b51dae9SMat Martineau }
29034b51dae9SMat Martineau 
l2cap_pass_to_tx_fbit(struct l2cap_chan * chan,struct l2cap_ctrl * control)2904f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2905f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2906f80842a8SMat Martineau {
2907f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2908401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2909f80842a8SMat Martineau }
2910f80842a8SMat Martineau 
29110a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
l2cap_raw_recv(struct l2cap_conn * conn,struct sk_buff * skb)29120a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
29130a708f8fSGustavo F. Padovan {
29140a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
291548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
29160a708f8fSGustavo F. Padovan 
29170a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
29180a708f8fSGustavo F. Padovan 
29193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
29203d57dc68SGustavo F. Padovan 
29213df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
2922715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
29230a708f8fSGustavo F. Padovan 			continue;
29240a708f8fSGustavo F. Padovan 
29257f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
2926a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
29270a708f8fSGustavo F. Padovan 			continue;
29287f5396a7SGustavo Padovan 
29298bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
29300a708f8fSGustavo F. Padovan 		if (!nskb)
29310a708f8fSGustavo F. Padovan 			continue;
293280b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
29330a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
29340a708f8fSGustavo F. Padovan 	}
29353d57dc68SGustavo F. Padovan 
29363df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
29370a708f8fSGustavo F. Padovan }
29380a708f8fSGustavo F. Padovan 
29390a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
l2cap_build_cmd(struct l2cap_conn * conn,u8 code,u8 ident,u16 dlen,void * data)2940b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2941b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
29420a708f8fSGustavo F. Padovan {
29430a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
29440a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
29450a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
29460a708f8fSGustavo F. Padovan 	int len, count;
29470a708f8fSGustavo F. Padovan 
2948b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
29490a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
29500a708f8fSGustavo F. Padovan 
2951300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
2952300b962eSAnderson Lizardo 		return NULL;
2953300b962eSAnderson Lizardo 
29540a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
29550a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
29560a708f8fSGustavo F. Padovan 
29578bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
29580a708f8fSGustavo F. Padovan 	if (!skb)
29590a708f8fSGustavo F. Padovan 		return NULL;
29600a708f8fSGustavo F. Padovan 
29614df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
29620a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
29633300d9a9SClaudio Takahasi 
29643300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
2965dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
29663300d9a9SClaudio Takahasi 	else
2967dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
29680a708f8fSGustavo F. Padovan 
29694df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
29700a708f8fSGustavo F. Padovan 	cmd->code  = code;
29710a708f8fSGustavo F. Padovan 	cmd->ident = ident;
29720a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
29730a708f8fSGustavo F. Padovan 
29740a708f8fSGustavo F. Padovan 	if (dlen) {
29750a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
297659ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
29770a708f8fSGustavo F. Padovan 		data += count;
29780a708f8fSGustavo F. Padovan 	}
29790a708f8fSGustavo F. Padovan 
29800a708f8fSGustavo F. Padovan 	len -= skb->len;
29810a708f8fSGustavo F. Padovan 
29820a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
29830a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
29840a708f8fSGustavo F. Padovan 	while (len) {
29850a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
29860a708f8fSGustavo F. Padovan 
29878bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
29880a708f8fSGustavo F. Padovan 		if (!*frag)
29890a708f8fSGustavo F. Padovan 			goto fail;
29900a708f8fSGustavo F. Padovan 
299159ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
29920a708f8fSGustavo F. Padovan 
29930a708f8fSGustavo F. Padovan 		len  -= count;
29940a708f8fSGustavo F. Padovan 		data += count;
29950a708f8fSGustavo F. Padovan 
29960a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
29970a708f8fSGustavo F. Padovan 	}
29980a708f8fSGustavo F. Padovan 
29990a708f8fSGustavo F. Padovan 	return skb;
30000a708f8fSGustavo F. Padovan 
30010a708f8fSGustavo F. Padovan fail:
30020a708f8fSGustavo F. Padovan 	kfree_skb(skb);
30030a708f8fSGustavo F. Padovan 	return NULL;
30040a708f8fSGustavo F. Padovan }
30050a708f8fSGustavo F. Padovan 
l2cap_get_conf_opt(void ** ptr,int * type,int * olen,unsigned long * val)30062d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
30072d792818SGustavo Padovan 				     unsigned long *val)
30080a708f8fSGustavo F. Padovan {
30090a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
30100a708f8fSGustavo F. Padovan 	int len;
30110a708f8fSGustavo F. Padovan 
30120a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
30130a708f8fSGustavo F. Padovan 	*ptr += len;
30140a708f8fSGustavo F. Padovan 
30150a708f8fSGustavo F. Padovan 	*type = opt->type;
30160a708f8fSGustavo F. Padovan 	*olen = opt->len;
30170a708f8fSGustavo F. Padovan 
30180a708f8fSGustavo F. Padovan 	switch (opt->len) {
30190a708f8fSGustavo F. Padovan 	case 1:
30200a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
30210a708f8fSGustavo F. Padovan 		break;
30220a708f8fSGustavo F. Padovan 
30230a708f8fSGustavo F. Padovan 	case 2:
30240a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
30250a708f8fSGustavo F. Padovan 		break;
30260a708f8fSGustavo F. Padovan 
30270a708f8fSGustavo F. Padovan 	case 4:
30280a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
30290a708f8fSGustavo F. Padovan 		break;
30300a708f8fSGustavo F. Padovan 
30310a708f8fSGustavo F. Padovan 	default:
30320a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
30330a708f8fSGustavo F. Padovan 		break;
30340a708f8fSGustavo F. Padovan 	}
30350a708f8fSGustavo F. Padovan 
3036b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
30370a708f8fSGustavo F. Padovan 	return len;
30380a708f8fSGustavo F. Padovan }
30390a708f8fSGustavo F. Padovan 
l2cap_add_conf_opt(void ** ptr,u8 type,u8 len,unsigned long val,size_t size)3040e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
30410a708f8fSGustavo F. Padovan {
30420a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
30430a708f8fSGustavo F. Padovan 
3044b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30450a708f8fSGustavo F. Padovan 
3046e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3047e860d2c9SBen Seri 		return;
3048e860d2c9SBen Seri 
30490a708f8fSGustavo F. Padovan 	opt->type = type;
30500a708f8fSGustavo F. Padovan 	opt->len  = len;
30510a708f8fSGustavo F. Padovan 
30520a708f8fSGustavo F. Padovan 	switch (len) {
30530a708f8fSGustavo F. Padovan 	case 1:
30540a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
30550a708f8fSGustavo F. Padovan 		break;
30560a708f8fSGustavo F. Padovan 
30570a708f8fSGustavo F. Padovan 	case 2:
30580a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
30590a708f8fSGustavo F. Padovan 		break;
30600a708f8fSGustavo F. Padovan 
30610a708f8fSGustavo F. Padovan 	case 4:
30620a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
30630a708f8fSGustavo F. Padovan 		break;
30640a708f8fSGustavo F. Padovan 
30650a708f8fSGustavo F. Padovan 	default:
30660a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
30670a708f8fSGustavo F. Padovan 		break;
30680a708f8fSGustavo F. Padovan 	}
30690a708f8fSGustavo F. Padovan 
30700a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
30710a708f8fSGustavo F. Padovan }
30720a708f8fSGustavo F. Padovan 
l2cap_add_opt_efs(void ** ptr,struct l2cap_chan * chan,size_t size)3073e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3074f89cef09SAndrei Emeltchenko {
3075f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3076f89cef09SAndrei Emeltchenko 
3077f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3078f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3079f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3080f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3081f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3082f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3083dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3084dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3085f89cef09SAndrei Emeltchenko 		break;
3086f89cef09SAndrei Emeltchenko 
3087f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3088f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3089f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3090f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3091f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3092f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3093f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3094f89cef09SAndrei Emeltchenko 		break;
3095f89cef09SAndrei Emeltchenko 
3096f89cef09SAndrei Emeltchenko 	default:
3097f89cef09SAndrei Emeltchenko 		return;
3098f89cef09SAndrei Emeltchenko 	}
3099f89cef09SAndrei Emeltchenko 
3100f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3101e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3102f89cef09SAndrei Emeltchenko }
3103f89cef09SAndrei Emeltchenko 
l2cap_ack_timeout(struct work_struct * work)3104721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
31050a708f8fSGustavo F. Padovan {
3106721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3107721c4181SGustavo F. Padovan 					       ack_timer.work);
31080362520bSMat Martineau 	u16 frames_to_ack;
31090a708f8fSGustavo F. Padovan 
31102fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
31112fb9b3d4SGustavo F. Padovan 
31126be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
31136be36555SAndrei Emeltchenko 
31140362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
31150362520bSMat Martineau 				     chan->last_acked_seq);
31160362520bSMat Martineau 
31170362520bSMat Martineau 	if (frames_to_ack)
31180362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
31196be36555SAndrei Emeltchenko 
31206be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
312109bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
31220a708f8fSGustavo F. Padovan }
31230a708f8fSGustavo F. Padovan 
l2cap_ertm_init(struct l2cap_chan * chan)3124466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
31250a708f8fSGustavo F. Padovan {
31263c588192SMat Martineau 	int err;
31273c588192SMat Martineau 
3128105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3129105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
313042e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
31316a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
313242e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
31336a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3134105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3135105bdf9eSMat Martineau 	chan->sdu = NULL;
3136105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3137105bdf9eSMat Martineau 	chan->sdu_len = 0;
3138105bdf9eSMat Martineau 
3139d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3140d34c34fbSMat Martineau 
3141105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3142105bdf9eSMat Martineau 		return 0;
3143105bdf9eSMat Martineau 
3144105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3145105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
31460a708f8fSGustavo F. Padovan 
3147f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
31480a708f8fSGustavo F. Padovan 
31493c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
31503c588192SMat Martineau 	if (err < 0)
31513c588192SMat Martineau 		return err;
31523c588192SMat Martineau 
31539dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
31549dc9affcSMat Martineau 	if (err < 0)
31559dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
31569dc9affcSMat Martineau 
31579dc9affcSMat Martineau 	return err;
31580a708f8fSGustavo F. Padovan }
31590a708f8fSGustavo F. Padovan 
l2cap_select_mode(__u8 mode,__u16 remote_feat_mask)31600a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
31610a708f8fSGustavo F. Padovan {
31620a708f8fSGustavo F. Padovan 	switch (mode) {
31630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
31640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
31650a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
31660a708f8fSGustavo F. Padovan 			return mode;
316719186c7bSGustavo A. R. Silva 		fallthrough;
31680a708f8fSGustavo F. Padovan 	default:
31690a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
31700a708f8fSGustavo F. Padovan 	}
31710a708f8fSGustavo F. Padovan }
31720a708f8fSGustavo F. Padovan 
__l2cap_ews_supported(struct l2cap_conn * conn)3173848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
31746327eb98SAndrei Emeltchenko {
3175cd5d26a9SLuiz Augusto von Dentz 	return (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW);
31766327eb98SAndrei Emeltchenko }
31776327eb98SAndrei Emeltchenko 
__l2cap_efs_supported(struct l2cap_conn * conn)3178848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3179f89cef09SAndrei Emeltchenko {
3180cd5d26a9SLuiz Augusto von Dentz 	return (conn->feat_mask & L2CAP_FEAT_EXT_FLOW);
3181f89cef09SAndrei Emeltchenko }
3182f89cef09SAndrei Emeltchenko 
__l2cap_set_ertm_timeouts(struct l2cap_chan * chan,struct l2cap_conf_rfc * rfc)318336c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
318436c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
318536c86c85SMat Martineau {
3186dcf4adbfSJoe Perches 	rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3187dcf4adbfSJoe Perches 	rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
318836c86c85SMat Martineau }
318936c86c85SMat Martineau 
l2cap_txwin_setup(struct l2cap_chan * chan)31906327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
31916327eb98SAndrei Emeltchenko {
31926327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3193848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
31946327eb98SAndrei Emeltchenko 		/* use extended control field */
31956327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3196836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3197836be934SAndrei Emeltchenko 	} else {
31986327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
31996327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3200836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3201836be934SAndrei Emeltchenko 	}
3202c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
32036327eb98SAndrei Emeltchenko }
32046327eb98SAndrei Emeltchenko 
l2cap_mtu_auto(struct l2cap_chan * chan)32054b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
32064b6e228eSLuiz Augusto von Dentz {
32074b6e228eSLuiz Augusto von Dentz 	struct hci_conn *conn = chan->conn->hcon;
32084b6e228eSLuiz Augusto von Dentz 
32094b6e228eSLuiz Augusto von Dentz 	chan->imtu = L2CAP_DEFAULT_MIN_MTU;
32104b6e228eSLuiz Augusto von Dentz 
32114b6e228eSLuiz Augusto von Dentz 	/* The 2-DH1 packet has between 2 and 56 information bytes
32124b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32134b6e228eSLuiz Augusto von Dentz 	 */
32144b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH1))
32154b6e228eSLuiz Augusto von Dentz 		chan->imtu = 54;
32164b6e228eSLuiz Augusto von Dentz 
32174b6e228eSLuiz Augusto von Dentz 	/* The 3-DH1 packet has between 2 and 85 information bytes
32184b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32194b6e228eSLuiz Augusto von Dentz 	 */
32204b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH1))
32214b6e228eSLuiz Augusto von Dentz 		chan->imtu = 83;
32224b6e228eSLuiz Augusto von Dentz 
32234b6e228eSLuiz Augusto von Dentz 	/* The 2-DH3 packet has between 2 and 369 information bytes
32244b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32254b6e228eSLuiz Augusto von Dentz 	 */
32264b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH3))
32274b6e228eSLuiz Augusto von Dentz 		chan->imtu = 367;
32284b6e228eSLuiz Augusto von Dentz 
32294b6e228eSLuiz Augusto von Dentz 	/* The 3-DH3 packet has between 2 and 554 information bytes
32304b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32314b6e228eSLuiz Augusto von Dentz 	 */
32324b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH3))
32334b6e228eSLuiz Augusto von Dentz 		chan->imtu = 552;
32344b6e228eSLuiz Augusto von Dentz 
32354b6e228eSLuiz Augusto von Dentz 	/* The 2-DH5 packet has between 2 and 681 information bytes
32364b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32374b6e228eSLuiz Augusto von Dentz 	 */
32384b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH5))
32394b6e228eSLuiz Augusto von Dentz 		chan->imtu = 679;
32404b6e228eSLuiz Augusto von Dentz 
32414b6e228eSLuiz Augusto von Dentz 	/* The 3-DH5 packet has between 2 and 1023 information bytes
32424b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
32434b6e228eSLuiz Augusto von Dentz 	 */
32444b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH5))
32454b6e228eSLuiz Augusto von Dentz 		chan->imtu = 1021;
32464b6e228eSLuiz Augusto von Dentz }
32474b6e228eSLuiz Augusto von Dentz 
l2cap_build_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)3248e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
32490a708f8fSGustavo F. Padovan {
32500a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
32510c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32520a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3253e860d2c9SBen Seri 	void *endptr = data + data_size;
3254c8f79162SAndrei Emeltchenko 	u16 size;
32550a708f8fSGustavo F. Padovan 
325649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
32570a708f8fSGustavo F. Padovan 
325873ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
32590a708f8fSGustavo F. Padovan 		goto done;
32600a708f8fSGustavo F. Padovan 
32610c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
32630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3264c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
32650a708f8fSGustavo F. Padovan 			break;
32660a708f8fSGustavo F. Padovan 
3267848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3268f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3269f89cef09SAndrei Emeltchenko 
327019186c7bSGustavo A. R. Silva 		fallthrough;
32710a708f8fSGustavo F. Padovan 	default:
32728c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
32730a708f8fSGustavo F. Padovan 		break;
32740a708f8fSGustavo F. Padovan 	}
32750a708f8fSGustavo F. Padovan 
32760a708f8fSGustavo F. Padovan done:
32774b6e228eSLuiz Augusto von Dentz 	if (chan->imtu != L2CAP_DEFAULT_MTU) {
32784b6e228eSLuiz Augusto von Dentz 		if (!chan->imtu)
32794b6e228eSLuiz Augusto von Dentz 			l2cap_mtu_auto(chan);
32804b6e228eSLuiz Augusto von Dentz 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
32814b6e228eSLuiz Augusto von Dentz 				   endptr - ptr);
32824b6e228eSLuiz Augusto von Dentz 	}
32830a708f8fSGustavo F. Padovan 
32840c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
32850a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
32866fea7ad1SMarcel Holtmann 		if (disable_ertm)
32876fea7ad1SMarcel Holtmann 			break;
32886fea7ad1SMarcel Holtmann 
32898c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
32908c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
32910a708f8fSGustavo F. Padovan 			break;
32920a708f8fSGustavo F. Padovan 
32930a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
32940a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
32950a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
32960a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
32970a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
32980a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
32990a708f8fSGustavo F. Padovan 
33000a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3301e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
33020a708f8fSGustavo F. Padovan 		break;
33030a708f8fSGustavo F. Padovan 
33040a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33050a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
330647d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
330736c86c85SMat Martineau 
330836c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3309c8f79162SAndrei Emeltchenko 
3310c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33112d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3312c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3313c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
33140a708f8fSGustavo F. Padovan 
33156327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
33166327eb98SAndrei Emeltchenko 
33176327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
33186327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
33190a708f8fSGustavo F. Padovan 
33200a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3321e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
33220a708f8fSGustavo F. Padovan 
3323f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3324e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3325f89cef09SAndrei Emeltchenko 
33266327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
33276327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3328e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
332960918918SAndrei Emeltchenko 
333060918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
333160918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3332f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
333360918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
333460918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3335e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
333660918918SAndrei Emeltchenko 			}
33370a708f8fSGustavo F. Padovan 		break;
33380a708f8fSGustavo F. Padovan 
33390a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3340273759e2SMat Martineau 		l2cap_txwin_setup(chan);
33410a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
33420a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
33430a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
33440a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
33450a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3346c8f79162SAndrei Emeltchenko 
3347c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
33482d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3349c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3350c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
33510a708f8fSGustavo F. Padovan 
33520a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3353e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
33540a708f8fSGustavo F. Padovan 
3355f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3356e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3357f89cef09SAndrei Emeltchenko 
335860918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
335947d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3360f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
336147d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
336260918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3363e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
33640a708f8fSGustavo F. Padovan 			}
33650a708f8fSGustavo F. Padovan 		break;
33660a708f8fSGustavo F. Padovan 	}
33670a708f8fSGustavo F. Padovan 
3368fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3369dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
33700a708f8fSGustavo F. Padovan 
33710a708f8fSGustavo F. Padovan 	return ptr - data;
33720a708f8fSGustavo F. Padovan }
33730a708f8fSGustavo F. Padovan 
l2cap_parse_conf_req(struct l2cap_chan * chan,void * data,size_t data_size)3374e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33750a708f8fSGustavo F. Padovan {
33760a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
33770a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3378e860d2c9SBen Seri 	void *endptr = data + data_size;
337973ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
338073ffa904SGustavo F. Padovan 	int len = chan->conf_len;
33810a708f8fSGustavo F. Padovan 	int type, hint, olen;
33820a708f8fSGustavo F. Padovan 	unsigned long val;
33830a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
338442dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
338542dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
33860a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
33870a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3388c8f79162SAndrei Emeltchenko 	u16 size;
33890a708f8fSGustavo F. Padovan 
339073ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
33910a708f8fSGustavo F. Padovan 
33920a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33930a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
33947c9cbd0bSMarcel Holtmann 		if (len < 0)
33957c9cbd0bSMarcel Holtmann 			break;
33960a708f8fSGustavo F. Padovan 
33970a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
33980a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
33990a708f8fSGustavo F. Padovan 
34000a708f8fSGustavo F. Padovan 		switch (type) {
34010a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3402af3d5d1cSMarcel Holtmann 			if (olen != 2)
3403af3d5d1cSMarcel Holtmann 				break;
34040a708f8fSGustavo F. Padovan 			mtu = val;
34050a708f8fSGustavo F. Padovan 			break;
34060a708f8fSGustavo F. Padovan 
34070a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3408af3d5d1cSMarcel Holtmann 			if (olen != 2)
3409af3d5d1cSMarcel Holtmann 				break;
34100c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
34110a708f8fSGustavo F. Padovan 			break;
34120a708f8fSGustavo F. Padovan 
34130a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
34140a708f8fSGustavo F. Padovan 			break;
34150a708f8fSGustavo F. Padovan 
34160a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3417af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3418af3d5d1cSMarcel Holtmann 				break;
34190a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
34200a708f8fSGustavo F. Padovan 			break;
34210a708f8fSGustavo F. Padovan 
34220a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3423af3d5d1cSMarcel Holtmann 			if (olen != 1)
3424af3d5d1cSMarcel Holtmann 				break;
34250a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3426f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
342742dceae2SAndrei Emeltchenko 			break;
34280a708f8fSGustavo F. Padovan 
342942dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3430af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3431af3d5d1cSMarcel Holtmann 				break;
343242dceae2SAndrei Emeltchenko 			remote_efs = 1;
343342dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
34340a708f8fSGustavo F. Padovan 			break;
34350a708f8fSGustavo F. Padovan 
34366327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3437af3d5d1cSMarcel Holtmann 			if (olen != 2)
3438af3d5d1cSMarcel Holtmann 				break;
34396327eb98SAndrei Emeltchenko 			return -ECONNREFUSED;
34400a708f8fSGustavo F. Padovan 
34410a708f8fSGustavo F. Padovan 		default:
34420a708f8fSGustavo F. Padovan 			if (hint)
34430a708f8fSGustavo F. Padovan 				break;
34440a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
34455b8ec15dSJimmy Wahlberg 			l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
34460a708f8fSGustavo F. Padovan 			break;
34470a708f8fSGustavo F. Padovan 		}
34480a708f8fSGustavo F. Padovan 	}
34490a708f8fSGustavo F. Padovan 
345073ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
34510a708f8fSGustavo F. Padovan 		goto done;
34520a708f8fSGustavo F. Padovan 
34530c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34540a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34550a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3456c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
34570c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
34588c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
34590a708f8fSGustavo F. Padovan 			break;
34600a708f8fSGustavo F. Padovan 		}
34610a708f8fSGustavo F. Padovan 
346242dceae2SAndrei Emeltchenko 		if (remote_efs) {
3463848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
346442dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
346542dceae2SAndrei Emeltchenko 			else
346642dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
346742dceae2SAndrei Emeltchenko 		}
346842dceae2SAndrei Emeltchenko 
34690c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
34700a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34710a708f8fSGustavo F. Padovan 
34720a708f8fSGustavo F. Padovan 		break;
34730a708f8fSGustavo F. Padovan 	}
34740a708f8fSGustavo F. Padovan 
34750a708f8fSGustavo F. Padovan done:
34760c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
34770a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
34780c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
34790a708f8fSGustavo F. Padovan 
348073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
34810a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
34820a708f8fSGustavo F. Padovan 
34832d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3484e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34850a708f8fSGustavo F. Padovan 	}
34860a708f8fSGustavo F. Padovan 
34870a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
34880a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
34890a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
34900a708f8fSGustavo F. Padovan 
34910a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
34920a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
34930a708f8fSGustavo F. Padovan 		else {
34940c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3495c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
34960a708f8fSGustavo F. Padovan 		}
3497e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34980a708f8fSGustavo F. Padovan 
349942dceae2SAndrei Emeltchenko 		if (remote_efs) {
350042dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
350142dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
350242dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
350342dceae2SAndrei Emeltchenko 
350442dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
350542dceae2SAndrei Emeltchenko 
350642dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
350742dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
350842dceae2SAndrei Emeltchenko 
350942dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
351042dceae2SAndrei Emeltchenko 						   sizeof(efs),
3511e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
35120e8b207eSAndrei Emeltchenko 			} else {
35133e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
35140e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
35150e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
351642dceae2SAndrei Emeltchenko 			}
351742dceae2SAndrei Emeltchenko 		}
351842dceae2SAndrei Emeltchenko 
35190a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
35200a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
352147d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3522c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35230a708f8fSGustavo F. Padovan 			break;
35240a708f8fSGustavo F. Padovan 
35250a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
35266327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
35272c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
35286327eb98SAndrei Emeltchenko 			else
35296327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
35306327eb98SAndrei Emeltchenko 
35312c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
35320a708f8fSGustavo F. Padovan 
3533c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35342d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35352d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3536c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3537c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35380a708f8fSGustavo F. Padovan 
353936c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
35400a708f8fSGustavo F. Padovan 
3541c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35420a708f8fSGustavo F. Padovan 
35430a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3544e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35450a708f8fSGustavo F. Padovan 
3546b1a2cd50SLuiz Augusto von Dentz 			if (remote_efs &&
3547b1a2cd50SLuiz Augusto von Dentz 			    test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
354842dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
354942dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
355042dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
355142dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
355242dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
355342dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
355442dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
355542dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
355642dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
355742dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
35582d792818SGustavo Padovan 						   sizeof(efs),
3559e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
356042dceae2SAndrei Emeltchenko 			}
35610a708f8fSGustavo F. Padovan 			break;
35620a708f8fSGustavo F. Padovan 
35630a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3564c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
35652d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
35662d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3567c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3568c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
35690a708f8fSGustavo F. Padovan 
3570c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
35710a708f8fSGustavo F. Padovan 
35722d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3573e860d2c9SBen Seri 					   (unsigned long) &rfc, endptr - ptr);
35740a708f8fSGustavo F. Padovan 
35750a708f8fSGustavo F. Padovan 			break;
35760a708f8fSGustavo F. Padovan 
35770a708f8fSGustavo F. Padovan 		default:
35780a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
35790a708f8fSGustavo F. Padovan 
35800a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
35810c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
35820a708f8fSGustavo F. Padovan 		}
35830a708f8fSGustavo F. Padovan 
35840a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3585c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
35860a708f8fSGustavo F. Padovan 	}
3587fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
35880a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
3589dcf4adbfSJoe Perches 	rsp->flags  = cpu_to_le16(0);
35900a708f8fSGustavo F. Padovan 
35910a708f8fSGustavo F. Padovan 	return ptr - data;
35920a708f8fSGustavo F. Padovan }
35930a708f8fSGustavo F. Padovan 
l2cap_parse_conf_rsp(struct l2cap_chan * chan,void * rsp,int len,void * data,size_t size,u16 * result)35942d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3595e860d2c9SBen Seri 				void *data, size_t size, u16 *result)
35960a708f8fSGustavo F. Padovan {
35970a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
35980a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3599e860d2c9SBen Seri 	void *endptr = data + size;
36000a708f8fSGustavo F. Padovan 	int type, olen;
36010a708f8fSGustavo F. Padovan 	unsigned long val;
360236e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
360366af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
36040a708f8fSGustavo F. Padovan 
3605fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
36060a708f8fSGustavo F. Padovan 
36070a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
36080a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
36097c9cbd0bSMarcel Holtmann 		if (len < 0)
36107c9cbd0bSMarcel Holtmann 			break;
36110a708f8fSGustavo F. Padovan 
36120a708f8fSGustavo F. Padovan 		switch (type) {
36130a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3614af3d5d1cSMarcel Holtmann 			if (olen != 2)
3615af3d5d1cSMarcel Holtmann 				break;
36160a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
36170a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
36180c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
36190a708f8fSGustavo F. Padovan 			} else
36200c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
3621af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3622af3d5d1cSMarcel Holtmann 					   endptr - ptr);
36230a708f8fSGustavo F. Padovan 			break;
36240a708f8fSGustavo F. Padovan 
36250a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3626af3d5d1cSMarcel Holtmann 			if (olen != 2)
3627af3d5d1cSMarcel Holtmann 				break;
36280c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
3629af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3630af3d5d1cSMarcel Holtmann 					   chan->flush_to, endptr - ptr);
36310a708f8fSGustavo F. Padovan 			break;
36320a708f8fSGustavo F. Padovan 
36330a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3634af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3635af3d5d1cSMarcel Holtmann 				break;
36360a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3637c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
36380c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
36390a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
364047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
3641af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3642af3d5d1cSMarcel Holtmann 					   (unsigned long) &rfc, endptr - ptr);
36430a708f8fSGustavo F. Padovan 			break;
36446327eb98SAndrei Emeltchenko 
36456327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3646af3d5d1cSMarcel Holtmann 			if (olen != 2)
3647af3d5d1cSMarcel Holtmann 				break;
3648c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
36493e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3650e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
36516327eb98SAndrei Emeltchenko 			break;
365266af7aafSAndrei Emeltchenko 
365366af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3654af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3655af3d5d1cSMarcel Holtmann 				break;
365666af7aafSAndrei Emeltchenko 			memcpy(&efs, (void *)val, olen);
365766af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
365866af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
365966af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
366066af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
36612d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3662e860d2c9SBen Seri 					   (unsigned long) &efs, endptr - ptr);
366366af7aafSAndrei Emeltchenko 			break;
3664cbabee78SAndrei Emeltchenko 
3665cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3666af3d5d1cSMarcel Holtmann 			if (olen != 1)
3667af3d5d1cSMarcel Holtmann 				break;
3668cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3669cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3670f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3671cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3672cbabee78SAndrei Emeltchenko 			break;
36730a708f8fSGustavo F. Padovan 		}
36740a708f8fSGustavo F. Padovan 	}
36750a708f8fSGustavo F. Padovan 
36760c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
36770a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
36780a708f8fSGustavo F. Padovan 
36790c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
36800a708f8fSGustavo F. Padovan 
36810e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
36820a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36830a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
368447d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
368547d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
368647d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3687c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3688c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3689c20f8e35SMat Martineau 						      rfc.txwin_size);
369066af7aafSAndrei Emeltchenko 
369166af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
369266af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
369366af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
369466af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
369566af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
369666af7aafSAndrei Emeltchenko 				chan->local_flush_to =
369766af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
369866af7aafSAndrei Emeltchenko 			}
36990a708f8fSGustavo F. Padovan 			break;
370066af7aafSAndrei Emeltchenko 
37010a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
370247d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
37030a708f8fSGustavo F. Padovan 		}
37040a708f8fSGustavo F. Padovan 	}
37050a708f8fSGustavo F. Padovan 
3706fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
3707dcf4adbfSJoe Perches 	req->flags  = cpu_to_le16(0);
37080a708f8fSGustavo F. Padovan 
37090a708f8fSGustavo F. Padovan 	return ptr - data;
37100a708f8fSGustavo F. Padovan }
37110a708f8fSGustavo F. Padovan 
l2cap_build_conf_rsp(struct l2cap_chan * chan,void * data,u16 result,u16 flags)37122d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
37132d792818SGustavo Padovan 				u16 result, u16 flags)
37140a708f8fSGustavo F. Padovan {
37150a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
37160a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
37170a708f8fSGustavo F. Padovan 
3718fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
37190a708f8fSGustavo F. Padovan 
3720fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37210a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
37220a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
37230a708f8fSGustavo F. Padovan 
37240a708f8fSGustavo F. Padovan 	return ptr - data;
37250a708f8fSGustavo F. Padovan }
37260a708f8fSGustavo F. Padovan 
__l2cap_le_connect_rsp_defer(struct l2cap_chan * chan)372727e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
372827e2d4c8SJohan Hedberg {
372927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
373027e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
373127e2d4c8SJohan Hedberg 
373227e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
373327e2d4c8SJohan Hedberg 
373427e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
373527e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
37363916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
37370cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
3738571f7390SMallikarjun Phulari 	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
373927e2d4c8SJohan Hedberg 
374027e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
374127e2d4c8SJohan Hedberg 		       &rsp);
374227e2d4c8SJohan Hedberg }
374327e2d4c8SJohan Hedberg 
l2cap_ecred_list_defer(struct l2cap_chan * chan,void * data)37449aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
374515f02b91SLuiz Augusto von Dentz {
37469aa9d947SLuiz Augusto von Dentz 	int *result = data;
374715f02b91SLuiz Augusto von Dentz 
37489aa9d947SLuiz Augusto von Dentz 	if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
374915f02b91SLuiz Augusto von Dentz 		return;
375015f02b91SLuiz Augusto von Dentz 
37519aa9d947SLuiz Augusto von Dentz 	switch (chan->state) {
37529aa9d947SLuiz Augusto von Dentz 	case BT_CONNECT2:
37539aa9d947SLuiz Augusto von Dentz 		/* If channel still pending accept add to result */
37549aa9d947SLuiz Augusto von Dentz 		(*result)++;
37559aa9d947SLuiz Augusto von Dentz 		return;
37569aa9d947SLuiz Augusto von Dentz 	case BT_CONNECTED:
37579aa9d947SLuiz Augusto von Dentz 		return;
37589aa9d947SLuiz Augusto von Dentz 	default:
37599aa9d947SLuiz Augusto von Dentz 		/* If not connected or pending accept it has been refused */
37609aa9d947SLuiz Augusto von Dentz 		*result = -ECONNREFUSED;
37619aa9d947SLuiz Augusto von Dentz 		return;
37629aa9d947SLuiz Augusto von Dentz 	}
37639aa9d947SLuiz Augusto von Dentz }
376415f02b91SLuiz Augusto von Dentz 
37659aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data {
37669aa9d947SLuiz Augusto von Dentz 	struct {
37679aa9d947SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
37689aa9d947SLuiz Augusto von Dentz 		__le16 scid[L2CAP_ECRED_MAX_CID];
37699aa9d947SLuiz Augusto von Dentz 	} __packed pdu;
37709aa9d947SLuiz Augusto von Dentz 	int count;
37719aa9d947SLuiz Augusto von Dentz };
377215f02b91SLuiz Augusto von Dentz 
l2cap_ecred_rsp_defer(struct l2cap_chan * chan,void * data)37739aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
37749aa9d947SLuiz Augusto von Dentz {
37759aa9d947SLuiz Augusto von Dentz 	struct l2cap_ecred_rsp_data *rsp = data;
377615f02b91SLuiz Augusto von Dentz 
37779aa9d947SLuiz Augusto von Dentz 	if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
37789aa9d947SLuiz Augusto von Dentz 		return;
377915f02b91SLuiz Augusto von Dentz 
378015f02b91SLuiz Augusto von Dentz 	/* Reset ident so only one response is sent */
378115f02b91SLuiz Augusto von Dentz 	chan->ident = 0;
378215f02b91SLuiz Augusto von Dentz 
378315f02b91SLuiz Augusto von Dentz 	/* Include all channels pending with the same ident */
37849aa9d947SLuiz Augusto von Dentz 	if (!rsp->pdu.rsp.result)
37859aa9d947SLuiz Augusto von Dentz 		rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
37869aa9d947SLuiz Augusto von Dentz 	else
37879aa9d947SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
378815f02b91SLuiz Augusto von Dentz }
378915f02b91SLuiz Augusto von Dentz 
__l2cap_ecred_conn_rsp_defer(struct l2cap_chan * chan)37909aa9d947SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
37919aa9d947SLuiz Augusto von Dentz {
37929aa9d947SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
37939aa9d947SLuiz Augusto von Dentz 	struct l2cap_ecred_rsp_data data;
37949aa9d947SLuiz Augusto von Dentz 	u16 id = chan->ident;
37959aa9d947SLuiz Augusto von Dentz 	int result = 0;
379615f02b91SLuiz Augusto von Dentz 
37979aa9d947SLuiz Augusto von Dentz 	if (!id)
37989aa9d947SLuiz Augusto von Dentz 		return;
37999aa9d947SLuiz Augusto von Dentz 
38009aa9d947SLuiz Augusto von Dentz 	BT_DBG("chan %p id %d", chan, id);
38019aa9d947SLuiz Augusto von Dentz 
38029aa9d947SLuiz Augusto von Dentz 	memset(&data, 0, sizeof(data));
38039aa9d947SLuiz Augusto von Dentz 
38049aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
38059aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.mps     = cpu_to_le16(chan->mps);
38069aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
38079aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
38089aa9d947SLuiz Augusto von Dentz 
38099aa9d947SLuiz Augusto von Dentz 	/* Verify that all channels are ready */
38109aa9d947SLuiz Augusto von Dentz 	__l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
38119aa9d947SLuiz Augusto von Dentz 
38129aa9d947SLuiz Augusto von Dentz 	if (result > 0)
38139aa9d947SLuiz Augusto von Dentz 		return;
38149aa9d947SLuiz Augusto von Dentz 
38159aa9d947SLuiz Augusto von Dentz 	if (result < 0)
38169aa9d947SLuiz Augusto von Dentz 		data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
38179aa9d947SLuiz Augusto von Dentz 
38189aa9d947SLuiz Augusto von Dentz 	/* Build response */
38199aa9d947SLuiz Augusto von Dentz 	__l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
38209aa9d947SLuiz Augusto von Dentz 
38219aa9d947SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
38229aa9d947SLuiz Augusto von Dentz 		       sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
38239aa9d947SLuiz Augusto von Dentz 		       &data.pdu);
382415f02b91SLuiz Augusto von Dentz }
382515f02b91SLuiz Augusto von Dentz 
__l2cap_connect_rsp_defer(struct l2cap_chan * chan)38268c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3827710f9b0aSGustavo F. Padovan {
3828710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
38298c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3830710f9b0aSGustavo F. Padovan 	u8 buf[128];
3831439f34acSAndrei Emeltchenko 	u8 rsp_code;
3832710f9b0aSGustavo F. Padovan 
3833fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3834fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3835dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3836dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3837439f34acSAndrei Emeltchenko 	rsp_code = L2CAP_CONN_RSP;
3838439f34acSAndrei Emeltchenko 
3839439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3840439f34acSAndrei Emeltchenko 
3841439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3842710f9b0aSGustavo F. Padovan 
3843c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3844710f9b0aSGustavo F. Padovan 		return;
3845710f9b0aSGustavo F. Padovan 
3846710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3847e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
3848710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3849710f9b0aSGustavo F. Padovan }
3850710f9b0aSGustavo F. Padovan 
l2cap_conf_rfc_get(struct l2cap_chan * chan,void * rsp,int len)385147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
38520a708f8fSGustavo F. Padovan {
38530a708f8fSGustavo F. Padovan 	int type, olen;
38540a708f8fSGustavo F. Padovan 	unsigned long val;
3855c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3856c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3857c20f8e35SMat Martineau 	 */
3858c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3859c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3860c20f8e35SMat Martineau 		.mode = chan->mode,
3861dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3862dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3863c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3864c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3865c20f8e35SMat Martineau 	};
38660a708f8fSGustavo F. Padovan 
386747d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
38680a708f8fSGustavo F. Padovan 
38690c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
38700a708f8fSGustavo F. Padovan 		return;
38710a708f8fSGustavo F. Padovan 
38720a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
38730a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
38747c9cbd0bSMarcel Holtmann 		if (len < 0)
38757c9cbd0bSMarcel Holtmann 			break;
38760a708f8fSGustavo F. Padovan 
3877c20f8e35SMat Martineau 		switch (type) {
3878c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3879af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3880af3d5d1cSMarcel Holtmann 				break;
38810a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3882c20f8e35SMat Martineau 			break;
3883c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3884af3d5d1cSMarcel Holtmann 			if (olen != 2)
3885af3d5d1cSMarcel Holtmann 				break;
3886c20f8e35SMat Martineau 			txwin_ext = val;
3887c20f8e35SMat Martineau 			break;
3888c20f8e35SMat Martineau 		}
38890a708f8fSGustavo F. Padovan 	}
38900a708f8fSGustavo F. Padovan 
38910a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
38920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
389347d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
389447d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
389547d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3896c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3897c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3898c20f8e35SMat Martineau 		else
3899c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3900c20f8e35SMat Martineau 					      rfc.txwin_size);
39010a708f8fSGustavo F. Padovan 		break;
39020a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
390347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
39040a708f8fSGustavo F. Padovan 	}
39050a708f8fSGustavo F. Padovan }
39060a708f8fSGustavo F. Padovan 
l2cap_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)39072d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3908cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3909cb3b3152SJohan Hedberg 				    u8 *data)
39100a708f8fSGustavo F. Padovan {
3911e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
39120a708f8fSGustavo F. Padovan 
3913cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3914cb3b3152SJohan Hedberg 		return -EPROTO;
3915cb3b3152SJohan Hedberg 
3916e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
39170a708f8fSGustavo F. Padovan 		return 0;
39180a708f8fSGustavo F. Padovan 
39190a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
39200a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
392117cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
39220a708f8fSGustavo F. Padovan 
39230a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39240a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39250a708f8fSGustavo F. Padovan 
39260a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39270a708f8fSGustavo F. Padovan 	}
39280a708f8fSGustavo F. Padovan 
39290a708f8fSGustavo F. Padovan 	return 0;
39300a708f8fSGustavo F. Padovan }
39310a708f8fSGustavo F. Padovan 
l2cap_connect(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u8 * data,u8 rsp_code)3932cfe560c7SSungwoo Kim static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
39335af2e235SLuiz Augusto von Dentz 			  u8 *data, u8 rsp_code)
39340a708f8fSGustavo F. Padovan {
39350a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39360a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
3937cfe560c7SSungwoo Kim 	struct l2cap_chan *chan = NULL, *pchan = NULL;
39380a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
39390a708f8fSGustavo F. Padovan 
39400a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
39410a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
39420a708f8fSGustavo F. Padovan 
3943097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
39440a708f8fSGustavo F. Padovan 
39450a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
39466f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3947bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
394823691d75SGustavo F. Padovan 	if (!pchan) {
39490a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
3950cfe560c7SSungwoo Kim 		goto response;
39510a708f8fSGustavo F. Padovan 	}
39520a708f8fSGustavo F. Padovan 
39533df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
39548ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
39550a708f8fSGustavo F. Padovan 
39560a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
3957dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
39580a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
39599f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39600a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
39610a708f8fSGustavo F. Padovan 		goto response;
39620a708f8fSGustavo F. Padovan 	}
39630a708f8fSGustavo F. Padovan 
39640a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
39650a708f8fSGustavo F. Padovan 
3966dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
3967dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
3968dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
39692dfa1003SGustavo Padovan 		goto response;
3970dd1a8f8aSMallikarjun Phulari 	}
3971dd1a8f8aSMallikarjun Phulari 
3972dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
3973dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
3974dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
3975dd1a8f8aSMallikarjun Phulari 		goto response;
3976dd1a8f8aSMallikarjun Phulari 	}
39772dfa1003SGustavo Padovan 
397880b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
397980808e43SGustavo F. Padovan 	if (!chan)
39800a708f8fSGustavo F. Padovan 		goto response;
39810a708f8fSGustavo F. Padovan 
3982330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
3983330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
3984330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
3985330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
3986330b6c15SSyam Sidhardhan 	 */
3987330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
3988330b6c15SSyam Sidhardhan 
39897eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
39907eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
3991a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
3992a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
3993fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3994fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
39950a708f8fSGustavo F. Padovan 
39966be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
399748454079SGustavo F. Padovan 
3998fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
39990a708f8fSGustavo F. Padovan 
40008d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
40010a708f8fSGustavo F. Padovan 
4002fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
40030a708f8fSGustavo F. Padovan 
40040a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4005e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
4006bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4007f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
40080a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
40090a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
40102dc4e510SGustavo Padovan 				chan->ops->defer(chan);
40110a708f8fSGustavo F. Padovan 			} else {
40127ccca396SPauli Virtanen 				l2cap_state_change(chan, BT_CONFIG);
40137ccca396SPauli Virtanen 				result = L2CAP_CR_SUCCESS;
40140a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
40150a708f8fSGustavo F. Padovan 			}
40160a708f8fSGustavo F. Padovan 		} else {
4017f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
40180a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
40190a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
40200a708f8fSGustavo F. Padovan 		}
40210a708f8fSGustavo F. Padovan 	} else {
4022f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
40230a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
40240a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
40250a708f8fSGustavo F. Padovan 	}
40260a708f8fSGustavo F. Padovan 
40270a708f8fSGustavo F. Padovan response:
40280a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
40290a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
40300a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
40310a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
40324c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40330a708f8fSGustavo F. Padovan 
4034cfe560c7SSungwoo Kim 	if (!pchan)
4035cfe560c7SSungwoo Kim 		return;
4036cfe560c7SSungwoo Kim 
40370a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40380a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4039dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
40400a708f8fSGustavo F. Padovan 
40410a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40420a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
40430a708f8fSGustavo F. Padovan 
4044ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40450a708f8fSGustavo F. Padovan 
40462d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40472d792818SGustavo Padovan 			       sizeof(info), &info);
40480a708f8fSGustavo F. Padovan 	}
40490a708f8fSGustavo F. Padovan 
4050c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40510a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
40520a708f8fSGustavo F. Padovan 		u8 buf[128];
4053c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
40540a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4055e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
405673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40570a708f8fSGustavo F. Padovan 	}
40581700915fSMat Martineau 
4059cfe560c7SSungwoo Kim 	l2cap_chan_unlock(pchan);
4060cfe560c7SSungwoo Kim 	mutex_unlock(&conn->chan_lock);
4061cfe560c7SSungwoo Kim 	l2cap_chan_put(pchan);
40624c89b6aaSMat Martineau }
40630a708f8fSGustavo F. Padovan 
l2cap_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40644c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4065cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40664c89b6aaSMat Martineau {
40677b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
40687b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
40697b064edaSJaganath Kanakkassery 
4070cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4071cb3b3152SJohan Hedberg 		return -EPROTO;
4072cb3b3152SJohan Hedberg 
40737b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
4074e2c680fcSArchie Pusaka 	if (hci_dev_test_flag(hdev, HCI_MGMT))
40751c6ed31bSYu Liu 		mgmt_device_connected(hdev, hcon, NULL, 0);
40767b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
40777b064edaSJaganath Kanakkassery 
40785af2e235SLuiz Augusto von Dentz 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP);
40790a708f8fSGustavo F. Padovan 	return 0;
40800a708f8fSGustavo F. Padovan }
40810a708f8fSGustavo F. Padovan 
l2cap_connect_create_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)40825909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4083cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4084cb3b3152SJohan Hedberg 				    u8 *data)
40850a708f8fSGustavo F. Padovan {
40860a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
40870a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
408848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
40890a708f8fSGustavo F. Padovan 	u8 req[128];
40903df91ea2SAndrei Emeltchenko 	int err;
40910a708f8fSGustavo F. Padovan 
4092cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4093cb3b3152SJohan Hedberg 		return -EPROTO;
4094cb3b3152SJohan Hedberg 
40950a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
40960a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
40970a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
40980a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
40990a708f8fSGustavo F. Padovan 
410075767213SSungwoo Kim 	if (result == L2CAP_CR_SUCCESS && (dcid < L2CAP_CID_DYN_START ||
410175767213SSungwoo Kim 					   dcid > L2CAP_CID_DYN_END))
410275767213SSungwoo Kim 		return -EPROTO;
410375767213SSungwoo Kim 
41041b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
41051b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
41060a708f8fSGustavo F. Padovan 
41073df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41083df91ea2SAndrei Emeltchenko 
41090a708f8fSGustavo F. Padovan 	if (scid) {
41103df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
41113df91ea2SAndrei Emeltchenko 		if (!chan) {
411221870b52SJohan Hedberg 			err = -EBADSLT;
41133df91ea2SAndrei Emeltchenko 			goto unlock;
41143df91ea2SAndrei Emeltchenko 		}
41150a708f8fSGustavo F. Padovan 	} else {
41163df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
41173df91ea2SAndrei Emeltchenko 		if (!chan) {
411821870b52SJohan Hedberg 			err = -EBADSLT;
41193df91ea2SAndrei Emeltchenko 			goto unlock;
41203df91ea2SAndrei Emeltchenko 		}
41210a708f8fSGustavo F. Padovan 	}
41220a708f8fSGustavo F. Padovan 
412335fcbc42SLuiz Augusto von Dentz 	chan = l2cap_chan_hold_unless_zero(chan);
412435fcbc42SLuiz Augusto von Dentz 	if (!chan) {
412535fcbc42SLuiz Augusto von Dentz 		err = -EBADSLT;
412635fcbc42SLuiz Augusto von Dentz 		goto unlock;
412735fcbc42SLuiz Augusto von Dentz 	}
412835fcbc42SLuiz Augusto von Dentz 
41293df91ea2SAndrei Emeltchenko 	err = 0;
41303df91ea2SAndrei Emeltchenko 
41316be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
413248454079SGustavo F. Padovan 
41330a708f8fSGustavo F. Padovan 	switch (result) {
41340a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
413575767213SSungwoo Kim 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
413675767213SSungwoo Kim 			err = -EBADSLT;
413775767213SSungwoo Kim 			break;
413875767213SSungwoo Kim 		}
413975767213SSungwoo Kim 
414089bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4141fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4142fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4143c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41440a708f8fSGustavo F. Padovan 
4145c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41460a708f8fSGustavo F. Padovan 			break;
41470a708f8fSGustavo F. Padovan 
41480a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4149e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
415073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41510a708f8fSGustavo F. Padovan 		break;
41520a708f8fSGustavo F. Padovan 
41530a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4154c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41550a708f8fSGustavo F. Padovan 		break;
41560a708f8fSGustavo F. Padovan 
41570a708f8fSGustavo F. Padovan 	default:
415848454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
41590a708f8fSGustavo F. Padovan 		break;
41600a708f8fSGustavo F. Padovan 	}
41610a708f8fSGustavo F. Padovan 
41626be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
416335fcbc42SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
41643df91ea2SAndrei Emeltchenko 
41653df91ea2SAndrei Emeltchenko unlock:
41663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
41673df91ea2SAndrei Emeltchenko 
41683df91ea2SAndrei Emeltchenko 	return err;
41690a708f8fSGustavo F. Padovan }
41700a708f8fSGustavo F. Padovan 
set_default_fcs(struct l2cap_chan * chan)417147d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41720a708f8fSGustavo F. Padovan {
41730a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
41740a708f8fSGustavo F. Padovan 	 * sides request it.
41750a708f8fSGustavo F. Padovan 	 */
41760c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
417747d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4178f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
417947d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
41800a708f8fSGustavo F. Padovan }
41810a708f8fSGustavo F. Padovan 
l2cap_send_efs_conf_rsp(struct l2cap_chan * chan,void * data,u8 ident,u16 flags)418229d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
418329d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
418429d8a590SAndrei Emeltchenko {
418529d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
418629d8a590SAndrei Emeltchenko 
418729d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
418829d8a590SAndrei Emeltchenko 	       flags);
418929d8a590SAndrei Emeltchenko 
419029d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
419129d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
419229d8a590SAndrei Emeltchenko 
419329d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
419429d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
419529d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
419629d8a590SAndrei Emeltchenko }
419729d8a590SAndrei Emeltchenko 
cmd_reject_invalid_cid(struct l2cap_conn * conn,u8 ident,u16 scid,u16 dcid)4198662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4199662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4200662d652dSJohan Hedberg {
4201662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4202662d652dSJohan Hedberg 
4203dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4204662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4205662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4206662d652dSJohan Hedberg 
4207662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4208662d652dSJohan Hedberg }
4209662d652dSJohan Hedberg 
l2cap_config_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)42102d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
42112d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
42122d792818SGustavo Padovan 				   u8 *data)
42130a708f8fSGustavo F. Padovan {
42140a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
42150a708f8fSGustavo F. Padovan 	u16 dcid, flags;
42160a708f8fSGustavo F. Padovan 	u8 rsp[64];
421748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42183c588192SMat Martineau 	int len, err = 0;
42190a708f8fSGustavo F. Padovan 
4220cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4221cb3b3152SJohan Hedberg 		return -EPROTO;
4222cb3b3152SJohan Hedberg 
42230a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
42240a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
42250a708f8fSGustavo F. Padovan 
42260a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42270a708f8fSGustavo F. Padovan 
4228baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4229662d652dSJohan Hedberg 	if (!chan) {
4230662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4231662d652dSJohan Hedberg 		return 0;
4232662d652dSJohan Hedberg 	}
42330a708f8fSGustavo F. Padovan 
423496298f64SHoward Chung 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
423596298f64SHoward Chung 	    chan->state != BT_CONNECTED) {
4236662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4237662d652dSJohan Hedberg 				       chan->dcid);
42380a708f8fSGustavo F. Padovan 		goto unlock;
42390a708f8fSGustavo F. Padovan 	}
42400a708f8fSGustavo F. Padovan 
42410a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
42420a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4243cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
42440a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4245fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42460a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
42470a708f8fSGustavo F. Padovan 		goto unlock;
42480a708f8fSGustavo F. Padovan 	}
42490a708f8fSGustavo F. Padovan 
42500a708f8fSGustavo F. Padovan 	/* Store config. */
425173ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
425273ffa904SGustavo F. Padovan 	chan->conf_len += len;
42530a708f8fSGustavo F. Padovan 
425459e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42550a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
42560a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4257fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42585325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
42590a708f8fSGustavo F. Padovan 		goto unlock;
42600a708f8fSGustavo F. Padovan 	}
42610a708f8fSGustavo F. Padovan 
42620a708f8fSGustavo F. Padovan 	/* Complete config. */
4263e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
42640a708f8fSGustavo F. Padovan 	if (len < 0) {
42655e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42660a708f8fSGustavo F. Padovan 		goto unlock;
42670a708f8fSGustavo F. Padovan 	}
42680a708f8fSGustavo F. Padovan 
42691500109bSMat Martineau 	chan->ident = cmd->ident;
42700a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
4271bcd70260SSungwoo Kim 	if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP)
427273ffa904SGustavo F. Padovan 		chan->num_conf_rsp++;
42730a708f8fSGustavo F. Padovan 
42740a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
427573ffa904SGustavo F. Padovan 	chan->conf_len = 0;
42760a708f8fSGustavo F. Padovan 
4277c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42780a708f8fSGustavo F. Padovan 		goto unlock;
42790a708f8fSGustavo F. Padovan 
4280c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
428147d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
42820a708f8fSGustavo F. Padovan 
4283105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4284105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
42853c588192SMat Martineau 			err = l2cap_ertm_init(chan);
42860a708f8fSGustavo F. Padovan 
42873c588192SMat Martineau 		if (err < 0)
42885e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
42893c588192SMat Martineau 		else
4290cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
42913c588192SMat Martineau 
42920a708f8fSGustavo F. Padovan 		goto unlock;
42930a708f8fSGustavo F. Padovan 	}
42940a708f8fSGustavo F. Padovan 
4295c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
42960a708f8fSGustavo F. Padovan 		u8 buf[64];
42970a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4298e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
429973ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43000a708f8fSGustavo F. Padovan 	}
43010a708f8fSGustavo F. Padovan 
430249c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
43030e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
43040e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
43050e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43060e8b207eSAndrei Emeltchenko 
43070e8b207eSAndrei Emeltchenko 		/* check compatibility */
43080e8b207eSAndrei Emeltchenko 
430979de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
431029d8a590SAndrei Emeltchenko 		l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
43110e8b207eSAndrei Emeltchenko 	}
43120e8b207eSAndrei Emeltchenko 
43130a708f8fSGustavo F. Padovan unlock:
43146be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
4315d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
43163c588192SMat Martineau 	return err;
43170a708f8fSGustavo F. Padovan }
43180a708f8fSGustavo F. Padovan 
l2cap_config_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)43192d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4320cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4321cb3b3152SJohan Hedberg 				   u8 *data)
43220a708f8fSGustavo F. Padovan {
43230a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43240a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
432548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4326cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
43273c588192SMat Martineau 	int err = 0;
43280a708f8fSGustavo F. Padovan 
4329cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4330cb3b3152SJohan Hedberg 		return -EPROTO;
4331cb3b3152SJohan Hedberg 
43320a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
43330a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
43340a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
43350a708f8fSGustavo F. Padovan 
433661386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
433761386cbaSAndrei Emeltchenko 	       result, len);
43380a708f8fSGustavo F. Padovan 
4339baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
434048454079SGustavo F. Padovan 	if (!chan)
43410a708f8fSGustavo F. Padovan 		return 0;
43420a708f8fSGustavo F. Padovan 
43430a708f8fSGustavo F. Padovan 	switch (result) {
43440a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
434547d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
43460e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43470a708f8fSGustavo F. Padovan 		break;
43480a708f8fSGustavo F. Padovan 
43490e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
43500e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43510e8b207eSAndrei Emeltchenko 
43520e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43530e8b207eSAndrei Emeltchenko 			char buf[64];
43540e8b207eSAndrei Emeltchenko 
43550e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4356e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
43570e8b207eSAndrei Emeltchenko 			if (len < 0) {
43585e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43590e8b207eSAndrei Emeltchenko 				goto done;
43600e8b207eSAndrei Emeltchenko 			}
43610e8b207eSAndrei Emeltchenko 
4362cd5d26a9SLuiz Augusto von Dentz 			l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 0);
43635ce66b59SAndrei Emeltchenko 		}
43640e8b207eSAndrei Emeltchenko 		goto done;
43650e8b207eSAndrei Emeltchenko 
436698d2c3e1SBastien Nocera 	case L2CAP_CONF_UNKNOWN:
43670a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
436873ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43690a708f8fSGustavo F. Padovan 			char req[64];
43700a708f8fSGustavo F. Padovan 
43710a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43725e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43730a708f8fSGustavo F. Padovan 				goto done;
43740a708f8fSGustavo F. Padovan 			}
43750a708f8fSGustavo F. Padovan 
43760a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
43770a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4378b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4379e860d2c9SBen Seri 						   req, sizeof(req), &result);
43800a708f8fSGustavo F. Padovan 			if (len < 0) {
43815e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43820a708f8fSGustavo F. Padovan 				goto done;
43830a708f8fSGustavo F. Padovan 			}
43840a708f8fSGustavo F. Padovan 
43850a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
43860a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
438773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
43880a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
43890a708f8fSGustavo F. Padovan 				goto done;
43900a708f8fSGustavo F. Padovan 			break;
43910a708f8fSGustavo F. Padovan 		}
439219186c7bSGustavo A. R. Silva 		fallthrough;
43930a708f8fSGustavo F. Padovan 
43940a708f8fSGustavo F. Padovan 	default:
43956be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
43962e0052e4SAndrei Emeltchenko 
4397ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
43985e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
43990a708f8fSGustavo F. Padovan 		goto done;
44000a708f8fSGustavo F. Padovan 	}
44010a708f8fSGustavo F. Padovan 
440259e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
44030a708f8fSGustavo F. Padovan 		goto done;
44040a708f8fSGustavo F. Padovan 
4405c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
44060a708f8fSGustavo F. Padovan 
4407c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
440847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44090a708f8fSGustavo F. Padovan 
4410105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4411105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44123c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44130a708f8fSGustavo F. Padovan 
44143c588192SMat Martineau 		if (err < 0)
44155e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44163c588192SMat Martineau 		else
4417cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44180a708f8fSGustavo F. Padovan 	}
44190a708f8fSGustavo F. Padovan 
44200a708f8fSGustavo F. Padovan done:
44216be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
4422d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
44233c588192SMat Martineau 	return err;
44240a708f8fSGustavo F. Padovan }
44250a708f8fSGustavo F. Padovan 
l2cap_disconnect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)44262d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4427cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4428cb3b3152SJohan Hedberg 				       u8 *data)
44290a708f8fSGustavo F. Padovan {
44300a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44310a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
44320a708f8fSGustavo F. Padovan 	u16 dcid, scid;
443348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44340a708f8fSGustavo F. Padovan 
4435cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4436cb3b3152SJohan Hedberg 		return -EPROTO;
4437cb3b3152SJohan Hedberg 
44380a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
44390a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
44400a708f8fSGustavo F. Padovan 
44410a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44420a708f8fSGustavo F. Padovan 
4443a2a9339eSLuiz Augusto von Dentz 	chan = l2cap_get_chan_by_scid(conn, dcid);
44443df91ea2SAndrei Emeltchenko 	if (!chan) {
4445662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4446662d652dSJohan Hedberg 		return 0;
44473df91ea2SAndrei Emeltchenko 	}
44480a708f8fSGustavo F. Padovan 
4449fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4450fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
44510a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44520a708f8fSGustavo F. Padovan 
44535ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
44540a708f8fSGustavo F. Padovan 
445502c5ea52SYing Hsu 	l2cap_chan_unlock(chan);
4456a2a9339eSLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
445702c5ea52SYing Hsu 	l2cap_chan_lock(chan);
445848454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
4459a2a9339eSLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
44606be36555SAndrei Emeltchenko 
446180b98027SGustavo Padovan 	chan->ops->close(chan);
44626c08fc89SManish Mandlik 
44636c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
446461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44653df91ea2SAndrei Emeltchenko 
44660a708f8fSGustavo F. Padovan 	return 0;
44670a708f8fSGustavo F. Padovan }
44680a708f8fSGustavo F. Padovan 
l2cap_disconnect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)44692d792818SGustavo Padovan static inline int l2cap_disconnect_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_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44740a708f8fSGustavo F. Padovan 	u16 dcid, scid;
447548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44760a708f8fSGustavo F. Padovan 
4477cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4478cb3b3152SJohan Hedberg 		return -EPROTO;
4479cb3b3152SJohan Hedberg 
44800a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
44810a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
44820a708f8fSGustavo F. Padovan 
44830a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
44840a708f8fSGustavo F. Padovan 
4485a2a9339eSLuiz Augusto von Dentz 	chan = l2cap_get_chan_by_scid(conn, scid);
44863df91ea2SAndrei Emeltchenko 	if (!chan) {
44870a708f8fSGustavo F. Padovan 		return 0;
44883df91ea2SAndrei Emeltchenko 	}
44890a708f8fSGustavo F. Padovan 
449028261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
449128261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
44926c08fc89SManish Mandlik 		l2cap_chan_put(chan);
449328261da8SMatias Karhumaa 		return 0;
449428261da8SMatias Karhumaa 	}
449528261da8SMatias Karhumaa 
449602c5ea52SYing Hsu 	l2cap_chan_unlock(chan);
4497a2a9339eSLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
449802c5ea52SYing Hsu 	l2cap_chan_lock(chan);
449948454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
4500a2a9339eSLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
45016be36555SAndrei Emeltchenko 
450280b98027SGustavo Padovan 	chan->ops->close(chan);
45036c08fc89SManish Mandlik 
45046c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
450561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
45063df91ea2SAndrei Emeltchenko 
45070a708f8fSGustavo F. Padovan 	return 0;
45080a708f8fSGustavo F. Padovan }
45090a708f8fSGustavo F. Padovan 
l2cap_information_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45102d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4511cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4512cb3b3152SJohan Hedberg 					u8 *data)
45130a708f8fSGustavo F. Padovan {
45140a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
45150a708f8fSGustavo F. Padovan 	u16 type;
45160a708f8fSGustavo F. Padovan 
4517cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4518cb3b3152SJohan Hedberg 		return -EPROTO;
4519cb3b3152SJohan Hedberg 
45200a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
45210a708f8fSGustavo F. Padovan 
45220a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
45230a708f8fSGustavo F. Padovan 
45240a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
45250a708f8fSGustavo F. Padovan 		u8 buf[8];
45260a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
45270a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4528dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4529dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45300a708f8fSGustavo F. Padovan 		if (!disable_ertm)
45310a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45320a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
4533a5fd6f30SAndrei Emeltchenko 
45340a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
45352d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45362d792818SGustavo Padovan 			       buf);
45370a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
45380a708f8fSGustavo F. Padovan 		u8 buf[12];
45390a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
454050a147cdSMat Martineau 
4541dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4542dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
45430bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
45440bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
45452d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45462d792818SGustavo Padovan 			       buf);
45470a708f8fSGustavo F. Padovan 	} else {
45480a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
45490a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4550dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
45512d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45522d792818SGustavo Padovan 			       &rsp);
45530a708f8fSGustavo F. Padovan 	}
45540a708f8fSGustavo F. Padovan 
45550a708f8fSGustavo F. Padovan 	return 0;
45560a708f8fSGustavo F. Padovan }
45570a708f8fSGustavo F. Padovan 
l2cap_information_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)45582d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4559cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4560cb3b3152SJohan Hedberg 					u8 *data)
45610a708f8fSGustavo F. Padovan {
45620a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45630a708f8fSGustavo F. Padovan 	u16 type, result;
45640a708f8fSGustavo F. Padovan 
45653f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4566cb3b3152SJohan Hedberg 		return -EPROTO;
4567cb3b3152SJohan Hedberg 
45680a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
45690a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
45700a708f8fSGustavo F. Padovan 
45710a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
45720a708f8fSGustavo F. Padovan 
4573e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4574e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4575e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4576e90165beSAndrei Emeltchenko 		return 0;
4577e90165beSAndrei Emeltchenko 
457817cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
45790a708f8fSGustavo F. Padovan 
45800a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
45810a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
45820a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
45830a708f8fSGustavo F. Padovan 
45840a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
45850a708f8fSGustavo F. Padovan 
45860a708f8fSGustavo F. Padovan 		return 0;
45870a708f8fSGustavo F. Padovan 	}
45880a708f8fSGustavo F. Padovan 
4589978c93b9SAndrei Emeltchenko 	switch (type) {
4590978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
45910a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
45920a708f8fSGustavo F. Padovan 
45930a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
45940a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4595dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
45960a708f8fSGustavo F. Padovan 
45970a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
45980a708f8fSGustavo F. Padovan 
45990a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
46000a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
46010a708f8fSGustavo F. Padovan 		} else {
46020a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46030a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
46040a708f8fSGustavo F. Padovan 
46050a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
46060a708f8fSGustavo F. Padovan 		}
4607978c93b9SAndrei Emeltchenko 		break;
4608978c93b9SAndrei Emeltchenko 
4609978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
46100bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
46110a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46120a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46130a708f8fSGustavo F. Padovan 
46140a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4615978c93b9SAndrei Emeltchenko 		break;
46160a708f8fSGustavo F. Padovan 	}
46170a708f8fSGustavo F. Padovan 
46180a708f8fSGustavo F. Padovan 	return 0;
46190a708f8fSGustavo F. Padovan }
46200a708f8fSGustavo F. Padovan 
l2cap_conn_param_update_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4621de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
46222d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
4623203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
4624de73115aSClaudio Takahasi {
4625de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
4626de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
4627de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
4628203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
46292ce603ebSClaudio Takahasi 	int err;
4630de73115aSClaudio Takahasi 
463140bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
4632de73115aSClaudio Takahasi 		return -EINVAL;
4633de73115aSClaudio Takahasi 
4634de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4635de73115aSClaudio Takahasi 		return -EPROTO;
4636de73115aSClaudio Takahasi 
4637de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4638de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4639de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4640de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4641de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4642de73115aSClaudio Takahasi 
4643de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4644de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
4645de73115aSClaudio Takahasi 
4646de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
46472ce603ebSClaudio Takahasi 
4648d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
46492ce603ebSClaudio Takahasi 	if (err)
4650dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4651de73115aSClaudio Takahasi 	else
4652dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4653de73115aSClaudio Takahasi 
4654de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4655de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
4656de73115aSClaudio Takahasi 
4657ffb5a827SAndre Guedes 	if (!err) {
4658f4869e2aSJohan Hedberg 		u8 store_hint;
4659ffb5a827SAndre Guedes 
4660f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
4661f4869e2aSJohan Hedberg 						to_multiplier);
4662f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
4663f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
4664f4869e2aSJohan Hedberg 				    to_multiplier);
4665f4869e2aSJohan Hedberg 
4666ffb5a827SAndre Guedes 	}
46672ce603ebSClaudio Takahasi 
4668de73115aSClaudio Takahasi 	return 0;
4669de73115aSClaudio Takahasi }
4670de73115aSClaudio Takahasi 
l2cap_le_connect_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4671f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
4672f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4673f1496deeSJohan Hedberg 				u8 *data)
4674f1496deeSJohan Hedberg {
4675f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
46763e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
4677f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
4678f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
46793e64b7bdSJohan Hedberg 	int err, sec_level;
4680f1496deeSJohan Hedberg 
4681f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4682f1496deeSJohan Hedberg 		return -EPROTO;
4683f1496deeSJohan Hedberg 
4684f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
4685f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
4686f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
4687f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
4688f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
4689f1496deeSJohan Hedberg 
4690571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
469140624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
469240624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
4693f1496deeSJohan Hedberg 		return -EPROTO;
4694f1496deeSJohan Hedberg 
4695f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
4696f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
4697f1496deeSJohan Hedberg 
4698f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
4699f1496deeSJohan Hedberg 
4700f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
4701f1496deeSJohan Hedberg 	if (!chan) {
4702f1496deeSJohan Hedberg 		err = -EBADSLT;
4703f1496deeSJohan Hedberg 		goto unlock;
4704f1496deeSJohan Hedberg 	}
4705f1496deeSJohan Hedberg 
4706f1496deeSJohan Hedberg 	err = 0;
4707f1496deeSJohan Hedberg 
4708f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
4709f1496deeSJohan Hedberg 
4710f1496deeSJohan Hedberg 	switch (result) {
4711571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
471240624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
471340624183SJohan Hedberg 			err = -EBADSLT;
471440624183SJohan Hedberg 			break;
471540624183SJohan Hedberg 		}
471640624183SJohan Hedberg 
4717f1496deeSJohan Hedberg 		chan->ident = 0;
4718f1496deeSJohan Hedberg 		chan->dcid = dcid;
4719f1496deeSJohan Hedberg 		chan->omtu = mtu;
4720f1496deeSJohan Hedberg 		chan->remote_mps = mps;
47210cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
4722f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
4723f1496deeSJohan Hedberg 		break;
4724f1496deeSJohan Hedberg 
4725571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
4726571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
47273e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
47283e64b7bdSJohan Hedberg 		 * anything.
47293e64b7bdSJohan Hedberg 		 */
47303e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
47313e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
47323e64b7bdSJohan Hedberg 			break;
47333e64b7bdSJohan Hedberg 		}
47343e64b7bdSJohan Hedberg 
47353e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
47363e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
47373e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
47383e64b7bdSJohan Hedberg 
47393e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
47403e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
47413e64b7bdSJohan Hedberg 
47423e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
47433e64b7bdSJohan Hedberg 		break;
47443e64b7bdSJohan Hedberg 
4745f1496deeSJohan Hedberg 	default:
4746f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
4747f1496deeSJohan Hedberg 		break;
4748f1496deeSJohan Hedberg 	}
4749f1496deeSJohan Hedberg 
4750f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
4751f1496deeSJohan Hedberg 
4752f1496deeSJohan Hedberg unlock:
4753f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
4754f1496deeSJohan Hedberg 
4755f1496deeSJohan Hedberg 	return err;
4756f1496deeSJohan Hedberg }
4757f1496deeSJohan Hedberg 
l2cap_bredr_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)47583300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
47592d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
47602d792818SGustavo Padovan 				      u8 *data)
47613300d9a9SClaudio Takahasi {
47623300d9a9SClaudio Takahasi 	int err = 0;
47633300d9a9SClaudio Takahasi 
47643300d9a9SClaudio Takahasi 	switch (cmd->code) {
47653300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
4766cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
47673300d9a9SClaudio Takahasi 		break;
47683300d9a9SClaudio Takahasi 
47693300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
4770cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
47713300d9a9SClaudio Takahasi 		break;
47723300d9a9SClaudio Takahasi 
47733300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
47749245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
47753300d9a9SClaudio Takahasi 		break;
47763300d9a9SClaudio Takahasi 
47773300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
47783300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
47793300d9a9SClaudio Takahasi 		break;
47803300d9a9SClaudio Takahasi 
47813300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
47829245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
47833300d9a9SClaudio Takahasi 		break;
47843300d9a9SClaudio Takahasi 
47853300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
4786cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
47873300d9a9SClaudio Takahasi 		break;
47883300d9a9SClaudio Takahasi 
47893300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
47909245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
47913300d9a9SClaudio Takahasi 		break;
47923300d9a9SClaudio Takahasi 
47933300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
47943300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
47953300d9a9SClaudio Takahasi 		break;
47963300d9a9SClaudio Takahasi 
47973300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
47983300d9a9SClaudio Takahasi 		break;
47993300d9a9SClaudio Takahasi 
48003300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
4801cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
48023300d9a9SClaudio Takahasi 		break;
48033300d9a9SClaudio Takahasi 
48043300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
48059245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
48063300d9a9SClaudio Takahasi 		break;
48073300d9a9SClaudio Takahasi 
48083300d9a9SClaudio Takahasi 	default:
48093300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
48103300d9a9SClaudio Takahasi 		err = -EINVAL;
48113300d9a9SClaudio Takahasi 		break;
48123300d9a9SClaudio Takahasi 	}
48133300d9a9SClaudio Takahasi 
48143300d9a9SClaudio Takahasi 	return err;
48153300d9a9SClaudio Takahasi }
48163300d9a9SClaudio Takahasi 
l2cap_le_connect_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)481727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
481827e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
481927e2d4c8SJohan Hedberg 				u8 *data)
482027e2d4c8SJohan Hedberg {
482127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
482227e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
482327e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
48240cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
482527e2d4c8SJohan Hedberg 	__le16 psm;
482627e2d4c8SJohan Hedberg 	u8 result;
482727e2d4c8SJohan Hedberg 
482827e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
482927e2d4c8SJohan Hedberg 		return -EPROTO;
483027e2d4c8SJohan Hedberg 
483127e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
483227e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
483327e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
483427e2d4c8SJohan Hedberg 	psm  = req->psm;
483527e2d4c8SJohan Hedberg 	dcid = 0;
48360cd75f7eSJohan Hedberg 	credits = 0;
483727e2d4c8SJohan Hedberg 
483827e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
483927e2d4c8SJohan Hedberg 		return -EPROTO;
484027e2d4c8SJohan Hedberg 
484127e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
484227e2d4c8SJohan Hedberg 	       scid, mtu, mps);
484327e2d4c8SJohan Hedberg 
4844711f8c3fSLuiz Augusto von Dentz 	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
4845711f8c3fSLuiz Augusto von Dentz 	 * page 1059:
4846711f8c3fSLuiz Augusto von Dentz 	 *
4847711f8c3fSLuiz Augusto von Dentz 	 * Valid range: 0x0001-0x00ff
4848711f8c3fSLuiz Augusto von Dentz 	 *
4849711f8c3fSLuiz Augusto von Dentz 	 * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
4850711f8c3fSLuiz Augusto von Dentz 	 */
4851711f8c3fSLuiz Augusto von Dentz 	if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
4852711f8c3fSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
4853711f8c3fSLuiz Augusto von Dentz 		chan = NULL;
4854711f8c3fSLuiz Augusto von Dentz 		goto response;
4855711f8c3fSLuiz Augusto von Dentz 	}
4856711f8c3fSLuiz Augusto von Dentz 
485727e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
485827e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
485927e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
486027e2d4c8SJohan Hedberg 	if (!pchan) {
4861571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
486227e2d4c8SJohan Hedberg 		chan = NULL;
486327e2d4c8SJohan Hedberg 		goto response;
486427e2d4c8SJohan Hedberg 	}
486527e2d4c8SJohan Hedberg 
486627e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
486727e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
486827e2d4c8SJohan Hedberg 
486935dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
487035dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
4871571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
487227e2d4c8SJohan Hedberg 		chan = NULL;
487327e2d4c8SJohan Hedberg 		goto response_unlock;
487427e2d4c8SJohan Hedberg 	}
487527e2d4c8SJohan Hedberg 
48768a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
48778a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
4878571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
48798a7889ccSJohan Hedberg 		chan = NULL;
48808a7889ccSJohan Hedberg 		goto response_unlock;
48818a7889ccSJohan Hedberg 	}
48828a7889ccSJohan Hedberg 
488327e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
488427e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
4885571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
488627e2d4c8SJohan Hedberg 		chan = NULL;
488727e2d4c8SJohan Hedberg 		goto response_unlock;
488827e2d4c8SJohan Hedberg 	}
488927e2d4c8SJohan Hedberg 
489027e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
489127e2d4c8SJohan Hedberg 	if (!chan) {
4892571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
489327e2d4c8SJohan Hedberg 		goto response_unlock;
489427e2d4c8SJohan Hedberg 	}
489527e2d4c8SJohan Hedberg 
489627e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
489727e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
4898a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
4899a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
490027e2d4c8SJohan Hedberg 	chan->psm  = psm;
490127e2d4c8SJohan Hedberg 	chan->dcid = scid;
490227e2d4c8SJohan Hedberg 	chan->omtu = mtu;
490327e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
490427e2d4c8SJohan Hedberg 
490527e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
4906fe149310SLuiz Augusto von Dentz 
4907ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
4908fe149310SLuiz Augusto von Dentz 
490927e2d4c8SJohan Hedberg 	dcid = chan->scid;
49100cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
491127e2d4c8SJohan Hedberg 
491227e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
491327e2d4c8SJohan Hedberg 
491427e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
491527e2d4c8SJohan Hedberg 
491627e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
491727e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
4918434714dcSJohan Hedberg 		/* The following result value is actually not defined
4919434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
4920434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
4921434714dcSJohan Hedberg 		 * instead of sending a response.
4922434714dcSJohan Hedberg 		 */
492327e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
492427e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
492527e2d4c8SJohan Hedberg 	} else {
492627e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
4927571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
492827e2d4c8SJohan Hedberg 	}
492927e2d4c8SJohan Hedberg 
493027e2d4c8SJohan Hedberg response_unlock:
493127e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
493227e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
4933a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
493427e2d4c8SJohan Hedberg 
493527e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
493627e2d4c8SJohan Hedberg 		return 0;
493727e2d4c8SJohan Hedberg 
493827e2d4c8SJohan Hedberg response:
493927e2d4c8SJohan Hedberg 	if (chan) {
494027e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
49413916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
494227e2d4c8SJohan Hedberg 	} else {
494327e2d4c8SJohan Hedberg 		rsp.mtu = 0;
494427e2d4c8SJohan Hedberg 		rsp.mps = 0;
494527e2d4c8SJohan Hedberg 	}
494627e2d4c8SJohan Hedberg 
494727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
49480cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
494927e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
495027e2d4c8SJohan Hedberg 
495127e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
495227e2d4c8SJohan Hedberg 
495327e2d4c8SJohan Hedberg 	return 0;
495427e2d4c8SJohan Hedberg }
495527e2d4c8SJohan Hedberg 
l2cap_le_credits(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)4956fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
4957fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4958fad5fc89SJohan Hedberg 				   u8 *data)
4959fad5fc89SJohan Hedberg {
4960fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
4961fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
49620f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
4963fad5fc89SJohan Hedberg 
4964fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
4965fad5fc89SJohan Hedberg 		return -EPROTO;
4966fad5fc89SJohan Hedberg 
4967fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
4968fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
4969fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
4970fad5fc89SJohan Hedberg 
4971fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
4972fad5fc89SJohan Hedberg 
4973fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
4974fad5fc89SJohan Hedberg 	if (!chan)
4975fad5fc89SJohan Hedberg 		return -EBADSLT;
4976fad5fc89SJohan Hedberg 
49770f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
49780f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
49790f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
49800f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
49810f1bfe4eSJohan Hedberg 
49820f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
49830f1bfe4eSJohan Hedberg 		 * command reject packet.
49840f1bfe4eSJohan Hedberg 		 */
4985d0be8347SLuiz Augusto von Dentz 		goto unlock;
49860f1bfe4eSJohan Hedberg 	}
49870f1bfe4eSJohan Hedberg 
4988fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
4989fad5fc89SJohan Hedberg 
49908a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
49918a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
4992fad5fc89SJohan Hedberg 
4993fad5fc89SJohan Hedberg 	if (chan->tx_credits)
4994fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
4995fad5fc89SJohan Hedberg 
4996d0be8347SLuiz Augusto von Dentz unlock:
4997fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
4998d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
4999fad5fc89SJohan Hedberg 
5000fad5fc89SJohan Hedberg 	return 0;
5001fad5fc89SJohan Hedberg }
5002fad5fc89SJohan Hedberg 
l2cap_ecred_conn_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)500315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
500415f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
500515f02b91SLuiz Augusto von Dentz 				       u8 *data)
500615f02b91SLuiz Augusto von Dentz {
500715f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_req *req = (void *) data;
500815f02b91SLuiz Augusto von Dentz 	struct {
500915f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
50107cf3b1ddSLuiz Augusto von Dentz 		__le16 dcid[L2CAP_ECRED_MAX_CID];
501115f02b91SLuiz Augusto von Dentz 	} __packed pdu;
501215f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *pchan;
5013965995b7SYueHaibing 	u16 mtu, mps;
501415f02b91SLuiz Augusto von Dentz 	__le16 psm;
501515f02b91SLuiz Augusto von Dentz 	u8 result, len = 0;
501615f02b91SLuiz Augusto von Dentz 	int i, num_scid;
501715f02b91SLuiz Augusto von Dentz 	bool defer = false;
501815f02b91SLuiz Augusto von Dentz 
50194be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
50204be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
50214be5ca67SLuiz Augusto von Dentz 
502269d67b46SKonstantin Forostyan 	if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
502315f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
502415f02b91SLuiz Augusto von Dentz 		goto response;
502515f02b91SLuiz Augusto von Dentz 	}
502615f02b91SLuiz Augusto von Dentz 
50277cf3b1ddSLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
50287cf3b1ddSLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
50297cf3b1ddSLuiz Augusto von Dentz 
50307cf3b1ddSLuiz Augusto von Dentz 	if (num_scid > ARRAY_SIZE(pdu.dcid)) {
50317cf3b1ddSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
50327cf3b1ddSLuiz Augusto von Dentz 		goto response;
50337cf3b1ddSLuiz Augusto von Dentz 	}
50347cf3b1ddSLuiz Augusto von Dentz 
503515f02b91SLuiz Augusto von Dentz 	mtu  = __le16_to_cpu(req->mtu);
503615f02b91SLuiz Augusto von Dentz 	mps  = __le16_to_cpu(req->mps);
503715f02b91SLuiz Augusto von Dentz 
503815f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
503915f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_UNACCEPT_PARAMS;
504015f02b91SLuiz Augusto von Dentz 		goto response;
504115f02b91SLuiz Augusto von Dentz 	}
504215f02b91SLuiz Augusto von Dentz 
504315f02b91SLuiz Augusto von Dentz 	psm  = req->psm;
504415f02b91SLuiz Augusto von Dentz 
5045711f8c3fSLuiz Augusto von Dentz 	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
5046711f8c3fSLuiz Augusto von Dentz 	 * page 1059:
5047711f8c3fSLuiz Augusto von Dentz 	 *
5048711f8c3fSLuiz Augusto von Dentz 	 * Valid range: 0x0001-0x00ff
5049711f8c3fSLuiz Augusto von Dentz 	 *
5050711f8c3fSLuiz Augusto von Dentz 	 * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
5051711f8c3fSLuiz Augusto von Dentz 	 */
5052711f8c3fSLuiz Augusto von Dentz 	if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
5053711f8c3fSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
5054711f8c3fSLuiz Augusto von Dentz 		goto response;
5055711f8c3fSLuiz Augusto von Dentz 	}
5056711f8c3fSLuiz Augusto von Dentz 
505715f02b91SLuiz Augusto von Dentz 	BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
505815f02b91SLuiz Augusto von Dentz 
505915f02b91SLuiz Augusto von Dentz 	memset(&pdu, 0, sizeof(pdu));
506015f02b91SLuiz Augusto von Dentz 
506115f02b91SLuiz Augusto von Dentz 	/* Check if we have socket listening on psm */
506215f02b91SLuiz Augusto von Dentz 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
506315f02b91SLuiz Augusto von Dentz 					 &conn->hcon->dst, LE_LINK);
506415f02b91SLuiz Augusto von Dentz 	if (!pchan) {
506515f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
506615f02b91SLuiz Augusto von Dentz 		goto response;
506715f02b91SLuiz Augusto von Dentz 	}
506815f02b91SLuiz Augusto von Dentz 
506915f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
507015f02b91SLuiz Augusto von Dentz 	l2cap_chan_lock(pchan);
507115f02b91SLuiz Augusto von Dentz 
507215f02b91SLuiz Augusto von Dentz 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
507315f02b91SLuiz Augusto von Dentz 				     SMP_ALLOW_STK)) {
507415f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHENTICATION;
507515f02b91SLuiz Augusto von Dentz 		goto unlock;
507615f02b91SLuiz Augusto von Dentz 	}
507715f02b91SLuiz Augusto von Dentz 
507815f02b91SLuiz Augusto von Dentz 	result = L2CAP_CR_LE_SUCCESS;
507915f02b91SLuiz Augusto von Dentz 
508015f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
508115f02b91SLuiz Augusto von Dentz 		u16 scid = __le16_to_cpu(req->scid[i]);
508215f02b91SLuiz Augusto von Dentz 
508315f02b91SLuiz Augusto von Dentz 		BT_DBG("scid[%d] 0x%4.4x", i, scid);
508415f02b91SLuiz Augusto von Dentz 
508515f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = 0x0000;
508615f02b91SLuiz Augusto von Dentz 		len += sizeof(*pdu.dcid);
508715f02b91SLuiz Augusto von Dentz 
508815f02b91SLuiz Augusto von Dentz 		/* Check for valid dynamic CID range */
508915f02b91SLuiz Augusto von Dentz 		if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
509015f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_INVALID_SCID;
509115f02b91SLuiz Augusto von Dentz 			continue;
509215f02b91SLuiz Augusto von Dentz 		}
509315f02b91SLuiz Augusto von Dentz 
509415f02b91SLuiz Augusto von Dentz 		/* Check if we already have channel with that dcid */
509515f02b91SLuiz Augusto von Dentz 		if (__l2cap_get_chan_by_dcid(conn, scid)) {
509615f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_SCID_IN_USE;
509715f02b91SLuiz Augusto von Dentz 			continue;
509815f02b91SLuiz Augusto von Dentz 		}
509915f02b91SLuiz Augusto von Dentz 
510015f02b91SLuiz Augusto von Dentz 		chan = pchan->ops->new_connection(pchan);
510115f02b91SLuiz Augusto von Dentz 		if (!chan) {
510215f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_NO_MEM;
510315f02b91SLuiz Augusto von Dentz 			continue;
510415f02b91SLuiz Augusto von Dentz 		}
510515f02b91SLuiz Augusto von Dentz 
510615f02b91SLuiz Augusto von Dentz 		bacpy(&chan->src, &conn->hcon->src);
510715f02b91SLuiz Augusto von Dentz 		bacpy(&chan->dst, &conn->hcon->dst);
510815f02b91SLuiz Augusto von Dentz 		chan->src_type = bdaddr_src_type(conn->hcon);
510915f02b91SLuiz Augusto von Dentz 		chan->dst_type = bdaddr_dst_type(conn->hcon);
511015f02b91SLuiz Augusto von Dentz 		chan->psm  = psm;
511115f02b91SLuiz Augusto von Dentz 		chan->dcid = scid;
511215f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
511315f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
511415f02b91SLuiz Augusto von Dentz 
511515f02b91SLuiz Augusto von Dentz 		__l2cap_chan_add(conn, chan);
511615f02b91SLuiz Augusto von Dentz 
511715f02b91SLuiz Augusto von Dentz 		l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
511815f02b91SLuiz Augusto von Dentz 
511915f02b91SLuiz Augusto von Dentz 		/* Init response */
512015f02b91SLuiz Augusto von Dentz 		if (!pdu.rsp.credits) {
512115f02b91SLuiz Augusto von Dentz 			pdu.rsp.mtu = cpu_to_le16(chan->imtu);
512215f02b91SLuiz Augusto von Dentz 			pdu.rsp.mps = cpu_to_le16(chan->mps);
512315f02b91SLuiz Augusto von Dentz 			pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
512415f02b91SLuiz Augusto von Dentz 		}
512515f02b91SLuiz Augusto von Dentz 
512615f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = cpu_to_le16(chan->scid);
512715f02b91SLuiz Augusto von Dentz 
512815f02b91SLuiz Augusto von Dentz 		__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
512915f02b91SLuiz Augusto von Dentz 
513015f02b91SLuiz Augusto von Dentz 		chan->ident = cmd->ident;
51319aa9d947SLuiz Augusto von Dentz 		chan->mode = L2CAP_MODE_EXT_FLOWCTL;
513215f02b91SLuiz Augusto von Dentz 
513315f02b91SLuiz Augusto von Dentz 		if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
513415f02b91SLuiz Augusto von Dentz 			l2cap_state_change(chan, BT_CONNECT2);
513515f02b91SLuiz Augusto von Dentz 			defer = true;
513615f02b91SLuiz Augusto von Dentz 			chan->ops->defer(chan);
513715f02b91SLuiz Augusto von Dentz 		} else {
513815f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
513915f02b91SLuiz Augusto von Dentz 		}
514015f02b91SLuiz Augusto von Dentz 	}
514115f02b91SLuiz Augusto von Dentz 
514215f02b91SLuiz Augusto von Dentz unlock:
514315f02b91SLuiz Augusto von Dentz 	l2cap_chan_unlock(pchan);
514415f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
514515f02b91SLuiz Augusto von Dentz 	l2cap_chan_put(pchan);
514615f02b91SLuiz Augusto von Dentz 
514715f02b91SLuiz Augusto von Dentz response:
514815f02b91SLuiz Augusto von Dentz 	pdu.rsp.result = cpu_to_le16(result);
514915f02b91SLuiz Augusto von Dentz 
515015f02b91SLuiz Augusto von Dentz 	if (defer)
515115f02b91SLuiz Augusto von Dentz 		return 0;
515215f02b91SLuiz Augusto von Dentz 
515315f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
515415f02b91SLuiz Augusto von Dentz 		       sizeof(pdu.rsp) + len, &pdu);
515515f02b91SLuiz Augusto von Dentz 
515615f02b91SLuiz Augusto von Dentz 	return 0;
515715f02b91SLuiz Augusto von Dentz }
515815f02b91SLuiz Augusto von Dentz 
l2cap_ecred_conn_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)515915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
516015f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
516115f02b91SLuiz Augusto von Dentz 				       u8 *data)
516215f02b91SLuiz Augusto von Dentz {
516315f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
516415f02b91SLuiz Augusto von Dentz 	struct hci_conn *hcon = conn->hcon;
516515f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, credits, result;
5166de895b43SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *tmp;
516715f02b91SLuiz Augusto von Dentz 	int err = 0, sec_level;
516815f02b91SLuiz Augusto von Dentz 	int i = 0;
516915f02b91SLuiz Augusto von Dentz 
517015f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
517115f02b91SLuiz Augusto von Dentz 		return -EPROTO;
517215f02b91SLuiz Augusto von Dentz 
517315f02b91SLuiz Augusto von Dentz 	mtu     = __le16_to_cpu(rsp->mtu);
517415f02b91SLuiz Augusto von Dentz 	mps     = __le16_to_cpu(rsp->mps);
517515f02b91SLuiz Augusto von Dentz 	credits = __le16_to_cpu(rsp->credits);
517615f02b91SLuiz Augusto von Dentz 	result  = __le16_to_cpu(rsp->result);
517715f02b91SLuiz Augusto von Dentz 
517815f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
517915f02b91SLuiz Augusto von Dentz 	       result);
518015f02b91SLuiz Augusto von Dentz 
518115f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
518215f02b91SLuiz Augusto von Dentz 
518315f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*rsp);
518415f02b91SLuiz Augusto von Dentz 
5185de895b43SLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
518615f02b91SLuiz Augusto von Dentz 		u16 dcid;
518715f02b91SLuiz Augusto von Dentz 
518815f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident ||
518915f02b91SLuiz Augusto von Dentz 		    chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
519015f02b91SLuiz Augusto von Dentz 		    chan->state == BT_CONNECTED)
519115f02b91SLuiz Augusto von Dentz 			continue;
519215f02b91SLuiz Augusto von Dentz 
519315f02b91SLuiz Augusto von Dentz 		l2cap_chan_lock(chan);
519415f02b91SLuiz Augusto von Dentz 
519515f02b91SLuiz Augusto von Dentz 		/* Check that there is a dcid for each pending channel */
519615f02b91SLuiz Augusto von Dentz 		if (cmd_len < sizeof(dcid)) {
519715f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
519815f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
519915f02b91SLuiz Augusto von Dentz 			continue;
520015f02b91SLuiz Augusto von Dentz 		}
520115f02b91SLuiz Augusto von Dentz 
520215f02b91SLuiz Augusto von Dentz 		dcid = __le16_to_cpu(rsp->dcid[i++]);
520315f02b91SLuiz Augusto von Dentz 		cmd_len -= sizeof(u16);
520415f02b91SLuiz Augusto von Dentz 
520515f02b91SLuiz Augusto von Dentz 		BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
520615f02b91SLuiz Augusto von Dentz 
520715f02b91SLuiz Augusto von Dentz 		/* Check if dcid is already in use */
520815f02b91SLuiz Augusto von Dentz 		if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
520915f02b91SLuiz Augusto von Dentz 			/* If a device receives a
521015f02b91SLuiz Augusto von Dentz 			 * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
521115f02b91SLuiz Augusto von Dentz 			 * already-assigned Destination CID, then both the
521215f02b91SLuiz Augusto von Dentz 			 * original channel and the new channel shall be
521315f02b91SLuiz Augusto von Dentz 			 * immediately discarded and not used.
521415f02b91SLuiz Augusto von Dentz 			 */
521515f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
521615f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
521715f02b91SLuiz Augusto von Dentz 			chan = __l2cap_get_chan_by_dcid(conn, dcid);
521815f02b91SLuiz Augusto von Dentz 			l2cap_chan_lock(chan);
521915f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNRESET);
522015f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
522115f02b91SLuiz Augusto von Dentz 			continue;
522215f02b91SLuiz Augusto von Dentz 		}
522315f02b91SLuiz Augusto von Dentz 
522415f02b91SLuiz Augusto von Dentz 		switch (result) {
522515f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_AUTHENTICATION:
522615f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_ENCRYPTION:
522715f02b91SLuiz Augusto von Dentz 			/* If we already have MITM protection we can't do
522815f02b91SLuiz Augusto von Dentz 			 * anything.
522915f02b91SLuiz Augusto von Dentz 			 */
523015f02b91SLuiz Augusto von Dentz 			if (hcon->sec_level > BT_SECURITY_MEDIUM) {
523115f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
523215f02b91SLuiz Augusto von Dentz 				break;
523315f02b91SLuiz Augusto von Dentz 			}
523415f02b91SLuiz Augusto von Dentz 
523515f02b91SLuiz Augusto von Dentz 			sec_level = hcon->sec_level + 1;
523615f02b91SLuiz Augusto von Dentz 			if (chan->sec_level < sec_level)
523715f02b91SLuiz Augusto von Dentz 				chan->sec_level = sec_level;
523815f02b91SLuiz Augusto von Dentz 
523915f02b91SLuiz Augusto von Dentz 			/* We'll need to send a new Connect Request */
524015f02b91SLuiz Augusto von Dentz 			clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
524115f02b91SLuiz Augusto von Dentz 
524215f02b91SLuiz Augusto von Dentz 			smp_conn_security(hcon, chan->sec_level);
524315f02b91SLuiz Augusto von Dentz 			break;
524415f02b91SLuiz Augusto von Dentz 
524515f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_BAD_PSM:
524615f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
524715f02b91SLuiz Augusto von Dentz 			break;
524815f02b91SLuiz Augusto von Dentz 
524915f02b91SLuiz Augusto von Dentz 		default:
525015f02b91SLuiz Augusto von Dentz 			/* If dcid was not set it means channels was refused */
525115f02b91SLuiz Augusto von Dentz 			if (!dcid) {
525215f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
525315f02b91SLuiz Augusto von Dentz 				break;
525415f02b91SLuiz Augusto von Dentz 			}
525515f02b91SLuiz Augusto von Dentz 
525615f02b91SLuiz Augusto von Dentz 			chan->ident = 0;
525715f02b91SLuiz Augusto von Dentz 			chan->dcid = dcid;
525815f02b91SLuiz Augusto von Dentz 			chan->omtu = mtu;
525915f02b91SLuiz Augusto von Dentz 			chan->remote_mps = mps;
526015f02b91SLuiz Augusto von Dentz 			chan->tx_credits = credits;
526115f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
526215f02b91SLuiz Augusto von Dentz 			break;
526315f02b91SLuiz Augusto von Dentz 		}
526415f02b91SLuiz Augusto von Dentz 
526515f02b91SLuiz Augusto von Dentz 		l2cap_chan_unlock(chan);
526615f02b91SLuiz Augusto von Dentz 	}
526715f02b91SLuiz Augusto von Dentz 
526815f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
526915f02b91SLuiz Augusto von Dentz 
527015f02b91SLuiz Augusto von Dentz 	return err;
527115f02b91SLuiz Augusto von Dentz }
527215f02b91SLuiz Augusto von Dentz 
l2cap_ecred_reconf_req(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)527315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
527415f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
527515f02b91SLuiz Augusto von Dentz 					 u8 *data)
527615f02b91SLuiz Augusto von Dentz {
527715f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_req *req = (void *) data;
527815f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_rsp rsp;
527915f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, result;
528015f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
528115f02b91SLuiz Augusto von Dentz 	int i, num_scid;
528215f02b91SLuiz Augusto von Dentz 
52834be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
52844be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
52854be5ca67SLuiz Augusto von Dentz 
528615f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
528715f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
528815f02b91SLuiz Augusto von Dentz 		goto respond;
528915f02b91SLuiz Augusto von Dentz 	}
529015f02b91SLuiz Augusto von Dentz 
529115f02b91SLuiz Augusto von Dentz 	mtu = __le16_to_cpu(req->mtu);
529215f02b91SLuiz Augusto von Dentz 	mps = __le16_to_cpu(req->mps);
529315f02b91SLuiz Augusto von Dentz 
529415f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u", mtu, mps);
529515f02b91SLuiz Augusto von Dentz 
529615f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU) {
529715f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MTU;
529815f02b91SLuiz Augusto von Dentz 		goto respond;
529915f02b91SLuiz Augusto von Dentz 	}
530015f02b91SLuiz Augusto von Dentz 
530115f02b91SLuiz Augusto von Dentz 	if (mps < L2CAP_ECRED_MIN_MPS) {
530215f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MPS;
530315f02b91SLuiz Augusto von Dentz 		goto respond;
530415f02b91SLuiz Augusto von Dentz 	}
530515f02b91SLuiz Augusto von Dentz 
530615f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
530715f02b91SLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
530815f02b91SLuiz Augusto von Dentz 	result = L2CAP_RECONF_SUCCESS;
530915f02b91SLuiz Augusto von Dentz 
531015f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
531115f02b91SLuiz Augusto von Dentz 		u16 scid;
531215f02b91SLuiz Augusto von Dentz 
531315f02b91SLuiz Augusto von Dentz 		scid = __le16_to_cpu(req->scid[i]);
531415f02b91SLuiz Augusto von Dentz 		if (!scid)
531515f02b91SLuiz Augusto von Dentz 			return -EPROTO;
531615f02b91SLuiz Augusto von Dentz 
531715f02b91SLuiz Augusto von Dentz 		chan = __l2cap_get_chan_by_dcid(conn, scid);
531815f02b91SLuiz Augusto von Dentz 		if (!chan)
531915f02b91SLuiz Augusto von Dentz 			continue;
532015f02b91SLuiz Augusto von Dentz 
532115f02b91SLuiz Augusto von Dentz 		/* If the MTU value is decreased for any of the included
532215f02b91SLuiz Augusto von Dentz 		 * channels, then the receiver shall disconnect all
532315f02b91SLuiz Augusto von Dentz 		 * included channels.
532415f02b91SLuiz Augusto von Dentz 		 */
532515f02b91SLuiz Augusto von Dentz 		if (chan->omtu > mtu) {
532615f02b91SLuiz Augusto von Dentz 			BT_ERR("chan %p decreased MTU %u -> %u", chan,
532715f02b91SLuiz Augusto von Dentz 			       chan->omtu, mtu);
532815f02b91SLuiz Augusto von Dentz 			result = L2CAP_RECONF_INVALID_MTU;
532915f02b91SLuiz Augusto von Dentz 		}
533015f02b91SLuiz Augusto von Dentz 
533115f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
533215f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
533315f02b91SLuiz Augusto von Dentz 	}
533415f02b91SLuiz Augusto von Dentz 
533515f02b91SLuiz Augusto von Dentz respond:
533615f02b91SLuiz Augusto von Dentz 	rsp.result = cpu_to_le16(result);
533715f02b91SLuiz Augusto von Dentz 
533815f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
533915f02b91SLuiz Augusto von Dentz 		       &rsp);
534015f02b91SLuiz Augusto von Dentz 
534115f02b91SLuiz Augusto von Dentz 	return 0;
534215f02b91SLuiz Augusto von Dentz }
534315f02b91SLuiz Augusto von Dentz 
l2cap_ecred_reconf_rsp(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)534415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
534515f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
534615f02b91SLuiz Augusto von Dentz 					 u8 *data)
534715f02b91SLuiz Augusto von Dentz {
53481fa20d7dSLuiz Augusto von Dentz 	struct l2cap_chan *chan, *tmp;
534915f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
535015f02b91SLuiz Augusto von Dentz 	u16 result;
535115f02b91SLuiz Augusto von Dentz 
535215f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
535315f02b91SLuiz Augusto von Dentz 		return -EPROTO;
535415f02b91SLuiz Augusto von Dentz 
535515f02b91SLuiz Augusto von Dentz 	result = __le16_to_cpu(rsp->result);
535615f02b91SLuiz Augusto von Dentz 
535715f02b91SLuiz Augusto von Dentz 	BT_DBG("result 0x%4.4x", rsp->result);
535815f02b91SLuiz Augusto von Dentz 
535915f02b91SLuiz Augusto von Dentz 	if (!result)
536015f02b91SLuiz Augusto von Dentz 		return 0;
536115f02b91SLuiz Augusto von Dentz 
53621fa20d7dSLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
536315f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident)
536415f02b91SLuiz Augusto von Dentz 			continue;
536515f02b91SLuiz Augusto von Dentz 
536615f02b91SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
536715f02b91SLuiz Augusto von Dentz 	}
536815f02b91SLuiz Augusto von Dentz 
536915f02b91SLuiz Augusto von Dentz 	return 0;
537015f02b91SLuiz Augusto von Dentz }
537115f02b91SLuiz Augusto von Dentz 
l2cap_le_command_rej(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)537271fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
537371fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
537471fb4197SJohan Hedberg 				       u8 *data)
537571fb4197SJohan Hedberg {
537671fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
537771fb4197SJohan Hedberg 	struct l2cap_chan *chan;
537871fb4197SJohan Hedberg 
537971fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
538071fb4197SJohan Hedberg 		return -EPROTO;
538171fb4197SJohan Hedberg 
538271fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
538371fb4197SJohan Hedberg 
538471fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
538571fb4197SJohan Hedberg 	if (!chan)
538671fb4197SJohan Hedberg 		goto done;
538771fb4197SJohan Hedberg 
5388f752a0b3SZhengping Jiang 	chan = l2cap_chan_hold_unless_zero(chan);
5389f752a0b3SZhengping Jiang 	if (!chan)
5390f752a0b3SZhengping Jiang 		goto done;
5391f752a0b3SZhengping Jiang 
539271fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
539371fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
539471fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
5395f752a0b3SZhengping Jiang 	l2cap_chan_put(chan);
539671fb4197SJohan Hedberg 
539771fb4197SJohan Hedberg done:
539871fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
539971fb4197SJohan Hedberg 	return 0;
540071fb4197SJohan Hedberg }
540171fb4197SJohan Hedberg 
l2cap_le_sig_cmd(struct l2cap_conn * conn,struct l2cap_cmd_hdr * cmd,u16 cmd_len,u8 * data)54023300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5403203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5404203e639eSJohan Hedberg 				   u8 *data)
54053300d9a9SClaudio Takahasi {
5406b5ecba64SJohan Hedberg 	int err = 0;
5407b5ecba64SJohan Hedberg 
54083300d9a9SClaudio Takahasi 	switch (cmd->code) {
54093300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
541071fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
5411b5ecba64SJohan Hedberg 		break;
54123300d9a9SClaudio Takahasi 
54133300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5414b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5415b5ecba64SJohan Hedberg 		break;
54163300d9a9SClaudio Takahasi 
54173300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5418b5ecba64SJohan Hedberg 		break;
54193300d9a9SClaudio Takahasi 
5420f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5421f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5422b5ecba64SJohan Hedberg 		break;
5423f1496deeSJohan Hedberg 
542427e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5425b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5426b5ecba64SJohan Hedberg 		break;
542727e2d4c8SJohan Hedberg 
5428fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5429fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5430fad5fc89SJohan Hedberg 		break;
5431fad5fc89SJohan Hedberg 
543215f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_REQ:
543315f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
543415f02b91SLuiz Augusto von Dentz 		break;
543515f02b91SLuiz Augusto von Dentz 
543615f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_RSP:
543715f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
543815f02b91SLuiz Augusto von Dentz 		break;
543915f02b91SLuiz Augusto von Dentz 
544015f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_REQ:
544115f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
544215f02b91SLuiz Augusto von Dentz 		break;
544315f02b91SLuiz Augusto von Dentz 
544415f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_RSP:
544515f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
544615f02b91SLuiz Augusto von Dentz 		break;
544715f02b91SLuiz Augusto von Dentz 
54483defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5449b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5450b5ecba64SJohan Hedberg 		break;
54513defe01aSJohan Hedberg 
54523defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
54533defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5454b5ecba64SJohan Hedberg 		break;
54553defe01aSJohan Hedberg 
54563300d9a9SClaudio Takahasi 	default:
54573300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5458b5ecba64SJohan Hedberg 		err = -EINVAL;
5459b5ecba64SJohan Hedberg 		break;
54603300d9a9SClaudio Takahasi 	}
5461b5ecba64SJohan Hedberg 
5462b5ecba64SJohan Hedberg 	return err;
54633300d9a9SClaudio Takahasi }
54643300d9a9SClaudio Takahasi 
l2cap_le_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)5465c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5466c5623556SJohan Hedberg 					struct sk_buff *skb)
5467c5623556SJohan Hedberg {
546869c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
54694f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
54704f3e219dSMarcel Holtmann 	u16 len;
5471c5623556SJohan Hedberg 	int err;
5472c5623556SJohan Hedberg 
547369c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
54743b166295SMarcel Holtmann 		goto drop;
547569c4e4e8SJohan Hedberg 
54764f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
54774f3e219dSMarcel Holtmann 		goto drop;
5478c5623556SJohan Hedberg 
54794f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
54804f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5481c5623556SJohan Hedberg 
54824f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5483c5623556SJohan Hedberg 
54844f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
54854f3e219dSMarcel Holtmann 
54864f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5487c5623556SJohan Hedberg 		BT_DBG("corrupted command");
54884f3e219dSMarcel Holtmann 		goto drop;
5489c5623556SJohan Hedberg 	}
5490c5623556SJohan Hedberg 
5491203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5492c5623556SJohan Hedberg 	if (err) {
5493c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5494c5623556SJohan Hedberg 
5495c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5496c5623556SJohan Hedberg 
5497dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
54984f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5499c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5500c5623556SJohan Hedberg 	}
5501c5623556SJohan Hedberg 
55023b166295SMarcel Holtmann drop:
5503c5623556SJohan Hedberg 	kfree_skb(skb);
5504c5623556SJohan Hedberg }
5505c5623556SJohan Hedberg 
l2cap_sig_send_rej(struct l2cap_conn * conn,u16 ident)55060974347aSFrédéric Danis static inline void l2cap_sig_send_rej(struct l2cap_conn *conn, u16 ident)
55070974347aSFrédéric Danis {
55080974347aSFrédéric Danis 	struct l2cap_cmd_rej_unk rej;
55090974347aSFrédéric Danis 
55100974347aSFrédéric Danis 	rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
55110974347aSFrédéric Danis 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
55120974347aSFrédéric Danis }
55130974347aSFrédéric Danis 
l2cap_sig_channel(struct l2cap_conn * conn,struct sk_buff * skb)55143300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
55153300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
55160a708f8fSGustavo F. Padovan {
551769c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
551855cee73eSLuiz Augusto von Dentz 	struct l2cap_cmd_hdr *cmd;
55193300d9a9SClaudio Takahasi 	int err;
55200a708f8fSGustavo F. Padovan 
55210a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
55220a708f8fSGustavo F. Padovan 
552369c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
55243b166295SMarcel Holtmann 		goto drop;
552569c4e4e8SJohan Hedberg 
552655cee73eSLuiz Augusto von Dentz 	while (skb->len >= L2CAP_CMD_HDR_SIZE) {
552755cee73eSLuiz Augusto von Dentz 		u16 len;
55280a708f8fSGustavo F. Padovan 
552955cee73eSLuiz Augusto von Dentz 		cmd = (void *) skb->data;
553055cee73eSLuiz Augusto von Dentz 		skb_pull(skb, L2CAP_CMD_HDR_SIZE);
55310a708f8fSGustavo F. Padovan 
553255cee73eSLuiz Augusto von Dentz 		len = le16_to_cpu(cmd->len);
55330a708f8fSGustavo F. Padovan 
553455cee73eSLuiz Augusto von Dentz 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
553555cee73eSLuiz Augusto von Dentz 		       cmd->ident);
553655cee73eSLuiz Augusto von Dentz 
553755cee73eSLuiz Augusto von Dentz 		if (len > skb->len || !cmd->ident) {
55380a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
55390974347aSFrédéric Danis 			l2cap_sig_send_rej(conn, cmd->ident);
5540100089a1SFrédéric Danis 			skb_pull(skb, len > skb->len ? skb->len : len);
5541100089a1SFrédéric Danis 			continue;
55420a708f8fSGustavo F. Padovan 		}
55430a708f8fSGustavo F. Padovan 
554455cee73eSLuiz Augusto von Dentz 		err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
55450a708f8fSGustavo F. Padovan 		if (err) {
55462c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
55470974347aSFrédéric Danis 			l2cap_sig_send_rej(conn, cmd->ident);
55480a708f8fSGustavo F. Padovan 		}
55490a708f8fSGustavo F. Padovan 
555055cee73eSLuiz Augusto von Dentz 		skb_pull(skb, len);
55510a708f8fSGustavo F. Padovan 	}
55520a708f8fSGustavo F. Padovan 
55530974347aSFrédéric Danis 	if (skb->len > 0) {
55540974347aSFrédéric Danis 		BT_DBG("corrupted command");
55550974347aSFrédéric Danis 		l2cap_sig_send_rej(conn, 0);
55560974347aSFrédéric Danis 	}
55570974347aSFrédéric Danis 
55583b166295SMarcel Holtmann drop:
55590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
55600a708f8fSGustavo F. Padovan }
55610a708f8fSGustavo F. Padovan 
l2cap_check_fcs(struct l2cap_chan * chan,struct sk_buff * skb)556247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
55630a708f8fSGustavo F. Padovan {
55640a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5565e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5566e4ca6d98SAndrei Emeltchenko 
5567e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5568e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5569e4ca6d98SAndrei Emeltchenko 	else
5570e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
55710a708f8fSGustavo F. Padovan 
557247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
557303a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
55740a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
55750a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
55760a708f8fSGustavo F. Padovan 
55770a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
55780a708f8fSGustavo F. Padovan 			return -EBADMSG;
55790a708f8fSGustavo F. Padovan 	}
55800a708f8fSGustavo F. Padovan 	return 0;
55810a708f8fSGustavo F. Padovan }
55820a708f8fSGustavo F. Padovan 
l2cap_send_i_or_rr_or_rnr(struct l2cap_chan * chan)55836ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
55840a708f8fSGustavo F. Padovan {
5585e31f7633SMat Martineau 	struct l2cap_ctrl control;
55860a708f8fSGustavo F. Padovan 
5587e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
55880a708f8fSGustavo F. Padovan 
5589e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5590e31f7633SMat Martineau 	control.sframe = 1;
5591e31f7633SMat Martineau 	control.final = 1;
5592e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5593e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
55940a708f8fSGustavo F. Padovan 
5595e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5596e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5597e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
55980a708f8fSGustavo F. Padovan 	}
55990a708f8fSGustavo F. Padovan 
5600e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5601e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5602e31f7633SMat Martineau 		__set_retrans_timer(chan);
56030a708f8fSGustavo F. Padovan 
5604e31f7633SMat Martineau 	/* Send pending iframes */
5605525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
56060a708f8fSGustavo F. Padovan 
5607e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5608e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5609e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5610e31f7633SMat Martineau 		 * send it now.
5611e31f7633SMat Martineau 		 */
5612e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5613e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
56140a708f8fSGustavo F. Padovan 	}
56150a708f8fSGustavo F. Padovan }
56160a708f8fSGustavo F. Padovan 
append_skb_frag(struct sk_buff * skb,struct sk_buff * new_frag,struct sk_buff ** last_frag)56172d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
56182d792818SGustavo Padovan 			    struct sk_buff **last_frag)
56190a708f8fSGustavo F. Padovan {
562084084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
562184084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
562284084a31SMat Martineau 	 */
562384084a31SMat Martineau 	if (!skb_has_frag_list(skb))
562484084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
562584084a31SMat Martineau 
562684084a31SMat Martineau 	new_frag->next = NULL;
562784084a31SMat Martineau 
562884084a31SMat Martineau 	(*last_frag)->next = new_frag;
562984084a31SMat Martineau 	*last_frag = new_frag;
563084084a31SMat Martineau 
563184084a31SMat Martineau 	skb->len += new_frag->len;
563284084a31SMat Martineau 	skb->data_len += new_frag->len;
563384084a31SMat Martineau 	skb->truesize += new_frag->truesize;
563484084a31SMat Martineau }
563584084a31SMat Martineau 
l2cap_reassemble_sdu(struct l2cap_chan * chan,struct sk_buff * skb,struct l2cap_ctrl * control)56364b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
56374b51dae9SMat Martineau 				struct l2cap_ctrl *control)
563884084a31SMat Martineau {
563984084a31SMat Martineau 	int err = -EINVAL;
56400a708f8fSGustavo F. Padovan 
56414b51dae9SMat Martineau 	switch (control->sar) {
56427e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
564384084a31SMat Martineau 		if (chan->sdu)
564484084a31SMat Martineau 			break;
56450a708f8fSGustavo F. Padovan 
564680b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
564784084a31SMat Martineau 		break;
56480a708f8fSGustavo F. Padovan 
56497e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
565084084a31SMat Martineau 		if (chan->sdu)
565184084a31SMat Martineau 			break;
56520a708f8fSGustavo F. Padovan 
5653dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
5654dbb50887SDaniel Borkmann 			break;
5655dbb50887SDaniel Borkmann 
56566f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
565703a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
56580a708f8fSGustavo F. Padovan 
565984084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
566084084a31SMat Martineau 			err = -EMSGSIZE;
566184084a31SMat Martineau 			break;
566284084a31SMat Martineau 		}
56630a708f8fSGustavo F. Padovan 
566484084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
566584084a31SMat Martineau 			break;
566684084a31SMat Martineau 
566784084a31SMat Martineau 		chan->sdu = skb;
566884084a31SMat Martineau 		chan->sdu_last_frag = skb;
566984084a31SMat Martineau 
567084084a31SMat Martineau 		skb = NULL;
567184084a31SMat Martineau 		err = 0;
56720a708f8fSGustavo F. Padovan 		break;
56730a708f8fSGustavo F. Padovan 
56747e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
56756f61fd47SGustavo F. Padovan 		if (!chan->sdu)
567684084a31SMat Martineau 			break;
56770a708f8fSGustavo F. Padovan 
567884084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
567984084a31SMat Martineau 				&chan->sdu_last_frag);
568084084a31SMat Martineau 		skb = NULL;
56810a708f8fSGustavo F. Padovan 
568284084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
568384084a31SMat Martineau 			break;
56840a708f8fSGustavo F. Padovan 
568584084a31SMat Martineau 		err = 0;
56860a708f8fSGustavo F. Padovan 		break;
56870a708f8fSGustavo F. Padovan 
56887e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
56896f61fd47SGustavo F. Padovan 		if (!chan->sdu)
569084084a31SMat Martineau 			break;
56910a708f8fSGustavo F. Padovan 
569284084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
569384084a31SMat Martineau 				&chan->sdu_last_frag);
569484084a31SMat Martineau 		skb = NULL;
56950a708f8fSGustavo F. Padovan 
569684084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
569784084a31SMat Martineau 			break;
56980a708f8fSGustavo F. Padovan 
569980b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
57000a708f8fSGustavo F. Padovan 
570184084a31SMat Martineau 		if (!err) {
570284084a31SMat Martineau 			/* Reassembly complete */
570384084a31SMat Martineau 			chan->sdu = NULL;
570484084a31SMat Martineau 			chan->sdu_last_frag = NULL;
570584084a31SMat Martineau 			chan->sdu_len = 0;
57060a708f8fSGustavo F. Padovan 		}
57070a708f8fSGustavo F. Padovan 		break;
57080a708f8fSGustavo F. Padovan 	}
57090a708f8fSGustavo F. Padovan 
571084084a31SMat Martineau 	if (err) {
57110a708f8fSGustavo F. Padovan 		kfree_skb(skb);
57126f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
57136f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
571484084a31SMat Martineau 		chan->sdu_last_frag = NULL;
571584084a31SMat Martineau 		chan->sdu_len = 0;
571684084a31SMat Martineau 	}
57170a708f8fSGustavo F. Padovan 
571884084a31SMat Martineau 	return err;
57190a708f8fSGustavo F. Padovan }
57200a708f8fSGustavo F. Padovan 
l2cap_resegment(struct l2cap_chan * chan)572132b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
572232b32735SMat Martineau {
572332b32735SMat Martineau 	/* Placeholder */
572432b32735SMat Martineau 	return 0;
572532b32735SMat Martineau }
572632b32735SMat Martineau 
l2cap_chan_busy(struct l2cap_chan * chan,int busy)5727e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
57280a708f8fSGustavo F. Padovan {
572961aa4f5bSMat Martineau 	u8 event;
573061aa4f5bSMat Martineau 
573161aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
573261aa4f5bSMat Martineau 		return;
573361aa4f5bSMat Martineau 
573461aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
5735401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
57360a708f8fSGustavo F. Padovan }
57370a708f8fSGustavo F. Padovan 
l2cap_rx_queued_iframes(struct l2cap_chan * chan)5738d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
5739d2a7ac5dSMat Martineau {
574063838725SMat Martineau 	int err = 0;
574163838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
574263838725SMat Martineau 	 * until a gap is encountered.
574363838725SMat Martineau 	 */
574463838725SMat Martineau 
574563838725SMat Martineau 	BT_DBG("chan %p", chan);
574663838725SMat Martineau 
574763838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
574863838725SMat Martineau 		struct sk_buff *skb;
574963838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
575063838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
575163838725SMat Martineau 
575263838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
575363838725SMat Martineau 
575463838725SMat Martineau 		if (!skb)
575563838725SMat Martineau 			break;
575663838725SMat Martineau 
575763838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
575863838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
5759a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
576063838725SMat Martineau 		if (err)
576163838725SMat Martineau 			break;
576263838725SMat Martineau 	}
576363838725SMat Martineau 
576463838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
576563838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
576663838725SMat Martineau 		l2cap_send_ack(chan);
576763838725SMat Martineau 	}
576863838725SMat Martineau 
576963838725SMat Martineau 	return err;
5770d2a7ac5dSMat Martineau }
5771d2a7ac5dSMat Martineau 
l2cap_handle_srej(struct l2cap_chan * chan,struct l2cap_ctrl * control)5772d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
5773d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
5774d2a7ac5dSMat Martineau {
5775f80842a8SMat Martineau 	struct sk_buff *skb;
5776f80842a8SMat Martineau 
5777f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
5778f80842a8SMat Martineau 
5779f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
5780f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
57815e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5782f80842a8SMat Martineau 		return;
5783f80842a8SMat Martineau 	}
5784f80842a8SMat Martineau 
5785f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5786f80842a8SMat Martineau 
5787f80842a8SMat Martineau 	if (skb == NULL) {
5788f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
5789f80842a8SMat Martineau 		       control->reqseq);
5790f80842a8SMat Martineau 		return;
5791f80842a8SMat Martineau 	}
5792f80842a8SMat Martineau 
5793a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5794f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
57955e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5796f80842a8SMat Martineau 		return;
5797f80842a8SMat Martineau 	}
5798f80842a8SMat Martineau 
5799f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5800f80842a8SMat Martineau 
5801f80842a8SMat Martineau 	if (control->poll) {
5802f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
5803f80842a8SMat Martineau 
5804f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
5805f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
5806f80842a8SMat Martineau 		l2cap_ertm_send(chan);
5807f80842a8SMat Martineau 
5808f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5809f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
5810f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
5811f80842a8SMat Martineau 		}
5812f80842a8SMat Martineau 	} else {
5813f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
5814f80842a8SMat Martineau 
5815f80842a8SMat Martineau 		if (control->final) {
5816f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
5817f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
5818f80842a8SMat Martineau 						&chan->conn_state))
5819f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
5820f80842a8SMat Martineau 		} else {
5821f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
5822f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
5823f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
5824f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
5825f80842a8SMat Martineau 			}
5826f80842a8SMat Martineau 		}
5827f80842a8SMat Martineau 	}
5828d2a7ac5dSMat Martineau }
5829d2a7ac5dSMat Martineau 
l2cap_handle_rej(struct l2cap_chan * chan,struct l2cap_ctrl * control)5830d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
5831d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
5832d2a7ac5dSMat Martineau {
5833fcd289dfSMat Martineau 	struct sk_buff *skb;
5834fcd289dfSMat Martineau 
5835fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
5836fcd289dfSMat Martineau 
5837fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
5838fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
58395e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5840fcd289dfSMat Martineau 		return;
5841fcd289dfSMat Martineau 	}
5842fcd289dfSMat Martineau 
5843fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
5844fcd289dfSMat Martineau 
5845fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
5846a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
5847fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
58485e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
5849fcd289dfSMat Martineau 		return;
5850fcd289dfSMat Martineau 	}
5851fcd289dfSMat Martineau 
5852fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
5853fcd289dfSMat Martineau 
5854fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
5855fcd289dfSMat Martineau 
5856fcd289dfSMat Martineau 	if (control->final) {
5857fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
5858fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
5859fcd289dfSMat Martineau 	} else {
5860fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
5861fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
5862fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
5863fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
5864fcd289dfSMat Martineau 	}
5865d2a7ac5dSMat Martineau }
5866d2a7ac5dSMat Martineau 
l2cap_classify_txseq(struct l2cap_chan * chan,u16 txseq)58674b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
58684b51dae9SMat Martineau {
58694b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
58704b51dae9SMat Martineau 
58714b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
58724b51dae9SMat Martineau 	       chan->expected_tx_seq);
58734b51dae9SMat Martineau 
58744b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
58754b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
58764b51dae9SMat Martineau 		    chan->tx_win) {
58774b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
58784b51dae9SMat Martineau 			 * invalid packets.
58794b51dae9SMat Martineau 			 */
58804b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
58814b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
58824b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
58834b51dae9SMat Martineau 			} else {
58844b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
58854b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
58864b51dae9SMat Martineau 			}
58874b51dae9SMat Martineau 		}
58884b51dae9SMat Martineau 
58894b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
58904b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
58914b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
58924b51dae9SMat Martineau 		}
58934b51dae9SMat Martineau 
58944b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
58954b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
58964b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
58974b51dae9SMat Martineau 		}
58984b51dae9SMat Martineau 
58994b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
59004b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
59014b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
59024b51dae9SMat Martineau 		}
59034b51dae9SMat Martineau 	}
59044b51dae9SMat Martineau 
59054b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
59064b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
59074b51dae9SMat Martineau 		    chan->tx_win) {
59084b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
59094b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
59104b51dae9SMat Martineau 		} else {
59114b51dae9SMat Martineau 			BT_DBG("Expected");
59124b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
59134b51dae9SMat Martineau 		}
59144b51dae9SMat Martineau 	}
59154b51dae9SMat Martineau 
59164b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
59172d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
59184b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
59194b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
59204b51dae9SMat Martineau 	}
59214b51dae9SMat Martineau 
59224b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
59234b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
59244b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
59254b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
59264b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
59274b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
59284b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
59294b51dae9SMat Martineau 		 * request.
59304b51dae9SMat Martineau 		 *
59314b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
59324b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
59334b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
59344b51dae9SMat Martineau 		 *
59354b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
59364b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
59374b51dae9SMat Martineau 		 * causes a disconnect.
59384b51dae9SMat Martineau 		 */
59394b51dae9SMat Martineau 
59404b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
59414b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
59424b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
59434b51dae9SMat Martineau 		} else {
59444b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
59454b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
59464b51dae9SMat Martineau 		}
59474b51dae9SMat Martineau 	} else {
59484b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
59494b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
59504b51dae9SMat Martineau 	}
59514b51dae9SMat Martineau }
59524b51dae9SMat Martineau 
l2cap_rx_state_recv(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)5953d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
5954d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
5955d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
5956d2a7ac5dSMat Martineau {
59573aff8aacSMaxim Mikityanskiy 	struct l2cap_ctrl local_control;
5958d2a7ac5dSMat Martineau 	int err = 0;
5959941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
5960d2a7ac5dSMat Martineau 
5961d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
5962d2a7ac5dSMat Martineau 	       event);
5963d2a7ac5dSMat Martineau 
5964d2a7ac5dSMat Martineau 	switch (event) {
5965d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
5966d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
5967d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
5968d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
5969d2a7ac5dSMat Martineau 
5970d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5971d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
5972d2a7ac5dSMat Martineau 				       control->txseq);
5973d2a7ac5dSMat Martineau 				break;
5974d2a7ac5dSMat Martineau 			}
5975d2a7ac5dSMat Martineau 
5976d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
5977d2a7ac5dSMat Martineau 							   control->txseq);
5978d2a7ac5dSMat Martineau 
5979d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
5980941247f9SPeter Senna Tschudin 			skb_in_use = true;
5981d2a7ac5dSMat Martineau 
59823aff8aacSMaxim Mikityanskiy 			/* l2cap_reassemble_sdu may free skb, hence invalidate
59833aff8aacSMaxim Mikityanskiy 			 * control, so make a copy in advance to use it after
59843aff8aacSMaxim Mikityanskiy 			 * l2cap_reassemble_sdu returns and to avoid the race
59853aff8aacSMaxim Mikityanskiy 			 * condition, for example:
59863aff8aacSMaxim Mikityanskiy 			 *
59873aff8aacSMaxim Mikityanskiy 			 * The current thread calls:
59883aff8aacSMaxim Mikityanskiy 			 *   l2cap_reassemble_sdu
59893aff8aacSMaxim Mikityanskiy 			 *     chan->ops->recv == l2cap_sock_recv_cb
59903aff8aacSMaxim Mikityanskiy 			 *       __sock_queue_rcv_skb
59913aff8aacSMaxim Mikityanskiy 			 * Another thread calls:
59923aff8aacSMaxim Mikityanskiy 			 *   bt_sock_recvmsg
59933aff8aacSMaxim Mikityanskiy 			 *     skb_recv_datagram
59943aff8aacSMaxim Mikityanskiy 			 *     skb_free_datagram
59953aff8aacSMaxim Mikityanskiy 			 * Then the current thread tries to access control, but
59963aff8aacSMaxim Mikityanskiy 			 * it was freed by skb_free_datagram.
59973aff8aacSMaxim Mikityanskiy 			 */
59983aff8aacSMaxim Mikityanskiy 			local_control = *control;
5999d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6000d2a7ac5dSMat Martineau 			if (err)
6001d2a7ac5dSMat Martineau 				break;
6002d2a7ac5dSMat Martineau 
60033aff8aacSMaxim Mikityanskiy 			if (local_control.final) {
6004d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6005d2a7ac5dSMat Martineau 							&chan->conn_state)) {
60063aff8aacSMaxim Mikityanskiy 					local_control.final = 0;
60073aff8aacSMaxim Mikityanskiy 					l2cap_retransmit_all(chan, &local_control);
6008d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6009d2a7ac5dSMat Martineau 				}
6010d2a7ac5dSMat Martineau 			}
6011d2a7ac5dSMat Martineau 
6012d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6013d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6014d2a7ac5dSMat Martineau 			break;
6015d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6016d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6017d2a7ac5dSMat Martineau 
6018d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6019d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6020d2a7ac5dSMat Martineau 			 * when local busy is exited.
6021d2a7ac5dSMat Martineau 			 */
6022d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6023d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6024d2a7ac5dSMat Martineau 				       control->txseq);
6025d2a7ac5dSMat Martineau 				break;
6026d2a7ac5dSMat Martineau 			}
6027d2a7ac5dSMat Martineau 
6028d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6029d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6030d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6031d2a7ac5dSMat Martineau 			 */
6032d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6033941247f9SPeter Senna Tschudin 			skb_in_use = true;
6034d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6035d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6036d2a7ac5dSMat Martineau 
6037d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6038d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6039d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6040d2a7ac5dSMat Martineau 
6041d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6042d2a7ac5dSMat Martineau 			break;
6043d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6044d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6045d2a7ac5dSMat Martineau 			break;
6046d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6047d2a7ac5dSMat Martineau 			break;
6048d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6049d2a7ac5dSMat Martineau 		default:
60505e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6051d2a7ac5dSMat Martineau 			break;
6052d2a7ac5dSMat Martineau 		}
6053d2a7ac5dSMat Martineau 		break;
6054d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6055d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6056d2a7ac5dSMat Martineau 		if (control->final) {
6057d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6058d2a7ac5dSMat Martineau 
6059cd5d26a9SLuiz Augusto von Dentz 			if (!test_and_clear_bit(CONN_REJ_ACT,
6060cd5d26a9SLuiz Augusto von Dentz 						&chan->conn_state)) {
6061d2a7ac5dSMat Martineau 				control->final = 0;
6062d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6063d2a7ac5dSMat Martineau 			}
6064d2a7ac5dSMat Martineau 
6065d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6066d2a7ac5dSMat Martineau 		} else if (control->poll) {
6067d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6068d2a7ac5dSMat Martineau 		} else {
6069d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6070d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6071d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6072d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6073d2a7ac5dSMat Martineau 
6074d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6075d2a7ac5dSMat Martineau 		}
6076d2a7ac5dSMat Martineau 		break;
6077d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6078d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6079d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6080d2a7ac5dSMat Martineau 		if (control && control->poll) {
6081d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6082d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6083d2a7ac5dSMat Martineau 		}
6084d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6085d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6086d2a7ac5dSMat Martineau 		break;
6087d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6088d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6089d2a7ac5dSMat Martineau 		break;
6090d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6091d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6092d2a7ac5dSMat Martineau 		break;
6093d2a7ac5dSMat Martineau 	default:
6094d2a7ac5dSMat Martineau 		break;
6095d2a7ac5dSMat Martineau 	}
6096d2a7ac5dSMat Martineau 
6097d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6098d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6099d2a7ac5dSMat Martineau 		kfree_skb(skb);
6100d2a7ac5dSMat Martineau 	}
6101d2a7ac5dSMat Martineau 
6102d2a7ac5dSMat Martineau 	return err;
6103d2a7ac5dSMat Martineau }
6104d2a7ac5dSMat Martineau 
l2cap_rx_state_srej_sent(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6105d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6106d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6107d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6108d2a7ac5dSMat Martineau {
6109d2a7ac5dSMat Martineau 	int err = 0;
6110d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6111941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6112d2a7ac5dSMat Martineau 
6113d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6114d2a7ac5dSMat Martineau 	       event);
6115d2a7ac5dSMat Martineau 
6116d2a7ac5dSMat Martineau 	switch (event) {
6117d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6118d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6119d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6120d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6121d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6122d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6123941247f9SPeter Senna Tschudin 			skb_in_use = true;
6124d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6125d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6126d2a7ac5dSMat Martineau 
6127d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6128d2a7ac5dSMat Martineau 			break;
6129d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6130d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6131d2a7ac5dSMat Martineau 
6132d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6133d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6134941247f9SPeter Senna Tschudin 			skb_in_use = true;
6135d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6136d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6137d2a7ac5dSMat Martineau 
6138d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6139d2a7ac5dSMat Martineau 			if (err)
6140d2a7ac5dSMat Martineau 				break;
6141d2a7ac5dSMat Martineau 
6142d2a7ac5dSMat Martineau 			break;
6143d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6144d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6145d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6146d2a7ac5dSMat Martineau 			 * the missing frames.
6147d2a7ac5dSMat Martineau 			 */
6148d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6149941247f9SPeter Senna Tschudin 			skb_in_use = true;
6150d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6151d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6152d2a7ac5dSMat Martineau 
6153d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6154d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6155d2a7ac5dSMat Martineau 			break;
6156d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6157d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6158d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6159d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6160d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6161d2a7ac5dSMat Martineau 			 */
6162d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6163941247f9SPeter Senna Tschudin 			skb_in_use = true;
6164d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6165d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6166d2a7ac5dSMat Martineau 
6167d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6168d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6169d2a7ac5dSMat Martineau 			break;
6170d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6171d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6172d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6173d2a7ac5dSMat Martineau 			break;
6174d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6175d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6176d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6177d2a7ac5dSMat Martineau 			 */
6178d2a7ac5dSMat Martineau 			break;
6179d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6180d2a7ac5dSMat Martineau 			break;
6181d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6182d2a7ac5dSMat Martineau 		default:
61835e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6184d2a7ac5dSMat Martineau 			break;
6185d2a7ac5dSMat Martineau 		}
6186d2a7ac5dSMat Martineau 		break;
6187d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6188d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6189d2a7ac5dSMat Martineau 		if (control->final) {
6190d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6191d2a7ac5dSMat Martineau 
6192d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6193d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6194d2a7ac5dSMat Martineau 				control->final = 0;
6195d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6196d2a7ac5dSMat Martineau 			}
6197d2a7ac5dSMat Martineau 
6198d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6199d2a7ac5dSMat Martineau 		} else if (control->poll) {
6200d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6201d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6202d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6203d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6204d2a7ac5dSMat Martineau 			}
6205d2a7ac5dSMat Martineau 
6206d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6207d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6208d2a7ac5dSMat Martineau 		} else {
6209d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6210d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6211d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6212d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6213d2a7ac5dSMat Martineau 
6214d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6215d2a7ac5dSMat Martineau 		}
6216d2a7ac5dSMat Martineau 		break;
6217d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6218d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6219d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6220d2a7ac5dSMat Martineau 		if (control->poll) {
6221d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6222d2a7ac5dSMat Martineau 		} else {
6223d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6224d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6225d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6226d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6227d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6228d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6229d2a7ac5dSMat Martineau 		}
6230d2a7ac5dSMat Martineau 
6231d2a7ac5dSMat Martineau 		break;
6232d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6233d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6234d2a7ac5dSMat Martineau 		break;
6235d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6236d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6237d2a7ac5dSMat Martineau 		break;
6238d2a7ac5dSMat Martineau 	}
6239d2a7ac5dSMat Martineau 
6240d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6241d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6242d2a7ac5dSMat Martineau 		kfree_skb(skb);
6243d2a7ac5dSMat Martineau 	}
6244d2a7ac5dSMat Martineau 
6245d2a7ac5dSMat Martineau 	return err;
6246d2a7ac5dSMat Martineau }
6247d2a7ac5dSMat Martineau 
l2cap_finish_move(struct l2cap_chan * chan)624832b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
624932b32735SMat Martineau {
625032b32735SMat Martineau 	BT_DBG("chan %p", chan);
625132b32735SMat Martineau 
625232b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
6253ad3f7986SSungwoo Kim 	chan->conn->mtu = chan->conn->hcon->mtu;
625432b32735SMat Martineau 
625532b32735SMat Martineau 	return l2cap_resegment(chan);
625632b32735SMat Martineau }
625732b32735SMat Martineau 
l2cap_rx_state_wait_p(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)625832b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
625932b32735SMat Martineau 				 struct l2cap_ctrl *control,
626032b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
626132b32735SMat Martineau {
626232b32735SMat Martineau 	int err;
626332b32735SMat Martineau 
626432b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
626532b32735SMat Martineau 	       event);
626632b32735SMat Martineau 
626732b32735SMat Martineau 	if (!control->poll)
626832b32735SMat Martineau 		return -EPROTO;
626932b32735SMat Martineau 
627032b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
627132b32735SMat Martineau 
627232b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
627332b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
627432b32735SMat Martineau 	else
627532b32735SMat Martineau 		chan->tx_send_head = NULL;
627632b32735SMat Martineau 
627732b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
627832b32735SMat Martineau 	 * by the receiver.
627932b32735SMat Martineau 	 */
628032b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
628132b32735SMat Martineau 	chan->unacked_frames = 0;
628232b32735SMat Martineau 
628332b32735SMat Martineau 	err = l2cap_finish_move(chan);
628432b32735SMat Martineau 	if (err)
628532b32735SMat Martineau 		return err;
628632b32735SMat Martineau 
628732b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
628832b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
628932b32735SMat Martineau 
629032b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
629132b32735SMat Martineau 		return -EPROTO;
629232b32735SMat Martineau 
629332b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
629432b32735SMat Martineau }
629532b32735SMat Martineau 
l2cap_rx_state_wait_f(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)629632b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
629732b32735SMat Martineau 				 struct l2cap_ctrl *control,
629832b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
629932b32735SMat Martineau {
630032b32735SMat Martineau 	int err;
630132b32735SMat Martineau 
630232b32735SMat Martineau 	if (!control->final)
630332b32735SMat Martineau 		return -EPROTO;
630432b32735SMat Martineau 
630532b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
630632b32735SMat Martineau 
630732b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
630832b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
630932b32735SMat Martineau 
631032b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
631132b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
631232b32735SMat Martineau 	else
631332b32735SMat Martineau 		chan->tx_send_head = NULL;
631432b32735SMat Martineau 
631532b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
631632b32735SMat Martineau 	 * by the receiver.
631732b32735SMat Martineau 	 */
631832b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
631932b32735SMat Martineau 	chan->unacked_frames = 0;
6320ad3f7986SSungwoo Kim 	chan->conn->mtu = chan->conn->hcon->mtu;
632132b32735SMat Martineau 
632232b32735SMat Martineau 	err = l2cap_resegment(chan);
632332b32735SMat Martineau 
632432b32735SMat Martineau 	if (!err)
632532b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
632632b32735SMat Martineau 
632732b32735SMat Martineau 	return err;
632832b32735SMat Martineau }
632932b32735SMat Martineau 
__valid_reqseq(struct l2cap_chan * chan,u16 reqseq)6330d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6331d2a7ac5dSMat Martineau {
6332d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6333d2a7ac5dSMat Martineau 	u16 unacked;
6334d2a7ac5dSMat Martineau 
6335d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6336d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6337d2a7ac5dSMat Martineau }
6338d2a7ac5dSMat Martineau 
l2cap_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb,u8 event)6339cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6340cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
63410a708f8fSGustavo F. Padovan {
6342d2a7ac5dSMat Martineau 	int err = 0;
6343d2a7ac5dSMat Martineau 
6344d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6345d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6346d2a7ac5dSMat Martineau 
6347d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6348d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6349d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6350d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6351d2a7ac5dSMat Martineau 			break;
6352d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6353d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6354d2a7ac5dSMat Martineau 						       event);
6355d2a7ac5dSMat Martineau 			break;
635632b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
635732b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
635832b32735SMat Martineau 			break;
635932b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
636032b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
636132b32735SMat Martineau 			break;
6362d2a7ac5dSMat Martineau 		default:
6363d2a7ac5dSMat Martineau 			/* shut it down */
6364d2a7ac5dSMat Martineau 			break;
6365d2a7ac5dSMat Martineau 		}
6366d2a7ac5dSMat Martineau 	} else {
6367d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6368d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6369d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
63705e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6371d2a7ac5dSMat Martineau 	}
6372d2a7ac5dSMat Martineau 
6373d2a7ac5dSMat Martineau 	return err;
6374cec8ab6eSMat Martineau }
6375cec8ab6eSMat Martineau 
l2cap_stream_rx(struct l2cap_chan * chan,struct l2cap_ctrl * control,struct sk_buff * skb)6376cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6377cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6378cec8ab6eSMat Martineau {
63793aff8aacSMaxim Mikityanskiy 	/* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
63803aff8aacSMaxim Mikityanskiy 	 * the txseq field in advance to use it after l2cap_reassemble_sdu
63813aff8aacSMaxim Mikityanskiy 	 * returns and to avoid the race condition, for example:
63823aff8aacSMaxim Mikityanskiy 	 *
63833aff8aacSMaxim Mikityanskiy 	 * The current thread calls:
63843aff8aacSMaxim Mikityanskiy 	 *   l2cap_reassemble_sdu
63853aff8aacSMaxim Mikityanskiy 	 *     chan->ops->recv == l2cap_sock_recv_cb
63863aff8aacSMaxim Mikityanskiy 	 *       __sock_queue_rcv_skb
63873aff8aacSMaxim Mikityanskiy 	 * Another thread calls:
63883aff8aacSMaxim Mikityanskiy 	 *   bt_sock_recvmsg
63893aff8aacSMaxim Mikityanskiy 	 *     skb_recv_datagram
63903aff8aacSMaxim Mikityanskiy 	 *     skb_free_datagram
63913aff8aacSMaxim Mikityanskiy 	 * Then the current thread tries to access control, but it was freed by
63923aff8aacSMaxim Mikityanskiy 	 * skb_free_datagram.
63933aff8aacSMaxim Mikityanskiy 	 */
63943aff8aacSMaxim Mikityanskiy 	u16 txseq = control->txseq;
63953aff8aacSMaxim Mikityanskiy 
63964b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
63974b51dae9SMat Martineau 	       chan->rx_state);
63984b51dae9SMat Martineau 
63993aff8aacSMaxim Mikityanskiy 	if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
64004b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
64014b51dae9SMat Martineau 
640293917fd2SKai Ye 		BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
64034b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
64044b51dae9SMat Martineau 
64054b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
64064b51dae9SMat Martineau 
64074b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
64084b51dae9SMat Martineau 	} else {
64094b51dae9SMat Martineau 		if (chan->sdu) {
64104b51dae9SMat Martineau 			kfree_skb(chan->sdu);
64114b51dae9SMat Martineau 			chan->sdu = NULL;
64124b51dae9SMat Martineau 		}
64134b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
64144b51dae9SMat Martineau 		chan->sdu_len = 0;
64154b51dae9SMat Martineau 
64164b51dae9SMat Martineau 		if (skb) {
64174b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
64184b51dae9SMat Martineau 			kfree_skb(skb);
64194b51dae9SMat Martineau 		}
64204b51dae9SMat Martineau 	}
64214b51dae9SMat Martineau 
64223aff8aacSMaxim Mikityanskiy 	chan->last_acked_seq = txseq;
64233aff8aacSMaxim Mikityanskiy 	chan->expected_tx_seq = __next_seq(chan, txseq);
64244b51dae9SMat Martineau 
64259a544210SPrasanna Karthik 	return 0;
6426cec8ab6eSMat Martineau }
6427cec8ab6eSMat Martineau 
l2cap_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)6428cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6429cec8ab6eSMat Martineau {
6430a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
6431cec8ab6eSMat Martineau 	u16 len;
6432cec8ab6eSMat Martineau 	u8 event;
64330a708f8fSGustavo F. Padovan 
6434b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6435b76bbd66SMat Martineau 
64360a708f8fSGustavo F. Padovan 	len = skb->len;
64370a708f8fSGustavo F. Padovan 
64380a708f8fSGustavo F. Padovan 	/*
64390a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
64400a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6441cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
64420a708f8fSGustavo F. Padovan 	 */
644347d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
64440a708f8fSGustavo F. Padovan 		goto drop;
64450a708f8fSGustavo F. Padovan 
6446cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
644703a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
64480a708f8fSGustavo F. Padovan 
644947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
645003a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
64510a708f8fSGustavo F. Padovan 
645247d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
64535e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
64540a708f8fSGustavo F. Padovan 		goto drop;
64550a708f8fSGustavo F. Padovan 	}
64560a708f8fSGustavo F. Padovan 
6457f1942564SLuiz Augusto von Dentz 	if (chan->ops->filter) {
6458f1942564SLuiz Augusto von Dentz 		if (chan->ops->filter(chan, skb))
6459dbb50887SDaniel Borkmann 			goto drop;
6460f1942564SLuiz Augusto von Dentz 	}
6461dbb50887SDaniel Borkmann 
6462cec8ab6eSMat Martineau 	if (!control->sframe) {
6463cec8ab6eSMat Martineau 		int err;
64640a708f8fSGustavo F. Padovan 
6465cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6466cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6467cec8ab6eSMat Martineau 		       control->txseq);
6468836be934SAndrei Emeltchenko 
6469cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6470cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6471cec8ab6eSMat Martineau 		 */
6472cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
64730a708f8fSGustavo F. Padovan 			goto drop;
64740a708f8fSGustavo F. Padovan 
6475cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6476cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6477cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
64780a708f8fSGustavo F. Padovan 		} else {
6479cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6480cec8ab6eSMat Martineau 		}
6481cec8ab6eSMat Martineau 
6482cec8ab6eSMat Martineau 		if (err)
64835e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6484cec8ab6eSMat Martineau 	} else {
6485cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6486cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6487cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6488cec8ab6eSMat Martineau 		};
6489cec8ab6eSMat Martineau 
6490cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6491cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6492cec8ab6eSMat Martineau 			goto drop;
6493cec8ab6eSMat Martineau 
6494cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6495cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6496cec8ab6eSMat Martineau 		       control->super);
6497cec8ab6eSMat Martineau 
64980a708f8fSGustavo F. Padovan 		if (len != 0) {
64991bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
65005e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
65010a708f8fSGustavo F. Padovan 			goto drop;
65020a708f8fSGustavo F. Padovan 		}
65030a708f8fSGustavo F. Padovan 
6504cec8ab6eSMat Martineau 		/* Validate F and P bits */
6505cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6506cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6507cec8ab6eSMat Martineau 			goto drop;
6508cec8ab6eSMat Martineau 
6509cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6510cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
65115e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
65120a708f8fSGustavo F. Padovan 	}
65130a708f8fSGustavo F. Padovan 
65140a708f8fSGustavo F. Padovan 	return 0;
65150a708f8fSGustavo F. Padovan 
65160a708f8fSGustavo F. Padovan drop:
65170a708f8fSGustavo F. Padovan 	kfree_skb(skb);
65180a708f8fSGustavo F. Padovan 	return 0;
65190a708f8fSGustavo F. Padovan }
65200a708f8fSGustavo F. Padovan 
l2cap_chan_le_send_credits(struct l2cap_chan * chan)6521b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6522b1c325c2SJohan Hedberg {
6523b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6524b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6525e2310343SSebastian Urban 	u16 return_credits = l2cap_le_rx_credits(chan);
6526b1c325c2SJohan Hedberg 
652715f02b91SLuiz Augusto von Dentz 	if (chan->rx_credits >= return_credits)
652896cd8eaaSLuiz Augusto von Dentz 		return;
6529b1c325c2SJohan Hedberg 
653015f02b91SLuiz Augusto von Dentz 	return_credits -= chan->rx_credits;
653115f02b91SLuiz Augusto von Dentz 
6532b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6533b1c325c2SJohan Hedberg 
6534b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6535b1c325c2SJohan Hedberg 
6536b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6537b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6538b1c325c2SJohan Hedberg 
6539b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6540b1c325c2SJohan Hedberg 
6541b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6542b1c325c2SJohan Hedberg }
6543b1c325c2SJohan Hedberg 
l2cap_chan_rx_avail(struct l2cap_chan * chan,ssize_t rx_avail)6544e2310343SSebastian Urban void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail)
6545e2310343SSebastian Urban {
6546e2310343SSebastian Urban 	if (chan->rx_avail == rx_avail)
6547e2310343SSebastian Urban 		return;
6548e2310343SSebastian Urban 
6549e2310343SSebastian Urban 	BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail);
6550e2310343SSebastian Urban 
6551e2310343SSebastian Urban 	chan->rx_avail = rx_avail;
6552e2310343SSebastian Urban 
6553e2310343SSebastian Urban 	if (chan->state == BT_CONNECTED)
6554e2310343SSebastian Urban 		l2cap_chan_le_send_credits(chan);
6555e2310343SSebastian Urban }
6556e2310343SSebastian Urban 
l2cap_ecred_recv(struct l2cap_chan * chan,struct sk_buff * skb)655715f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
655896cd8eaaSLuiz Augusto von Dentz {
655996cd8eaaSLuiz Augusto von Dentz 	int err;
656096cd8eaaSLuiz Augusto von Dentz 
656196cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
656296cd8eaaSLuiz Augusto von Dentz 
656396cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
656496cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
656596cd8eaaSLuiz Augusto von Dentz 
6566e2310343SSebastian Urban 	if (err < 0 && chan->rx_avail != -1) {
6567e2310343SSebastian Urban 		BT_ERR("Queueing received LE L2CAP data failed");
6568e2310343SSebastian Urban 		l2cap_send_disconn_req(chan, ECONNRESET);
6569e2310343SSebastian Urban 		return err;
6570e2310343SSebastian Urban 	}
6571e2310343SSebastian Urban 
657296cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
657396cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
657496cd8eaaSLuiz Augusto von Dentz 
657596cd8eaaSLuiz Augusto von Dentz 	return err;
657696cd8eaaSLuiz Augusto von Dentz }
657796cd8eaaSLuiz Augusto von Dentz 
l2cap_ecred_data_rcv(struct l2cap_chan * chan,struct sk_buff * skb)657815f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6579fad5fc89SJohan Hedberg {
6580aac23bf6SJohan Hedberg 	int err;
6581fad5fc89SJohan Hedberg 
6582aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6583aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6584dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
6585fad5fc89SJohan Hedberg 		return -ENOBUFS;
6586aac23bf6SJohan Hedberg 	}
6587aac23bf6SJohan Hedberg 
6588aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6589aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6590aac23bf6SJohan Hedberg 		return -ENOBUFS;
6591aac23bf6SJohan Hedberg 	}
6592fad5fc89SJohan Hedberg 
6593fad5fc89SJohan Hedberg 	chan->rx_credits--;
6594e2310343SSebastian Urban 	BT_DBG("chan %p: rx_credits %u -> %u",
6595e2310343SSebastian Urban 	       chan, chan->rx_credits + 1, chan->rx_credits);
6596fad5fc89SJohan Hedberg 
659796cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
659896cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
659996cd8eaaSLuiz Augusto von Dentz 	 */
660096cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
6601fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
6602fad5fc89SJohan Hedberg 
6603aac23bf6SJohan Hedberg 	err = 0;
6604aac23bf6SJohan Hedberg 
6605aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6606aac23bf6SJohan Hedberg 		u16 sdu_len;
6607aac23bf6SJohan Hedberg 
6608aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6609aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6610aac23bf6SJohan Hedberg 
6611aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6612aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6613aac23bf6SJohan Hedberg 
6614aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6615aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6616aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6617aac23bf6SJohan Hedberg 			goto failed;
6618aac23bf6SJohan Hedberg 		}
6619aac23bf6SJohan Hedberg 
6620aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6621aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6622aac23bf6SJohan Hedberg 			err = -EINVAL;
6623aac23bf6SJohan Hedberg 			goto failed;
6624aac23bf6SJohan Hedberg 		}
6625aac23bf6SJohan Hedberg 
6626aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
662715f02b91SLuiz Augusto von Dentz 			return l2cap_ecred_recv(chan, skb);
6628aac23bf6SJohan Hedberg 
6629aac23bf6SJohan Hedberg 		chan->sdu = skb;
6630aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6631aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6632aac23bf6SJohan Hedberg 
6633a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
6634a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
6635a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
6636a5c3021bSLuiz Augusto von Dentz 
6637a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
6638a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
6639a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
6640a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
6641a5c3021bSLuiz Augusto von Dentz 		}
6642a5c3021bSLuiz Augusto von Dentz 
6643aac23bf6SJohan Hedberg 		return 0;
6644aac23bf6SJohan Hedberg 	}
6645aac23bf6SJohan Hedberg 
6646aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6647aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6648aac23bf6SJohan Hedberg 
6649aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6650aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6651aac23bf6SJohan Hedberg 		err = -EINVAL;
6652aac23bf6SJohan Hedberg 		goto failed;
6653aac23bf6SJohan Hedberg 	}
6654aac23bf6SJohan Hedberg 
6655aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6656aac23bf6SJohan Hedberg 	skb = NULL;
6657aac23bf6SJohan Hedberg 
6658aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
665915f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_recv(chan, chan->sdu);
6660aac23bf6SJohan Hedberg 		if (!err) {
6661aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6662aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6663aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6664aac23bf6SJohan Hedberg 		}
6665aac23bf6SJohan Hedberg 	}
6666aac23bf6SJohan Hedberg 
6667aac23bf6SJohan Hedberg failed:
6668aac23bf6SJohan Hedberg 	if (err) {
6669aac23bf6SJohan Hedberg 		kfree_skb(skb);
6670aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6671aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6672aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6673aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6674aac23bf6SJohan Hedberg 	}
6675aac23bf6SJohan Hedberg 
6676aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6677aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6678aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6679aac23bf6SJohan Hedberg 	 */
6680aac23bf6SJohan Hedberg 	return 0;
6681fad5fc89SJohan Hedberg }
6682fad5fc89SJohan Hedberg 
l2cap_data_channel(struct l2cap_conn * conn,u16 cid,struct sk_buff * skb)668313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
668413ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
66850a708f8fSGustavo F. Padovan {
668648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
66870a708f8fSGustavo F. Padovan 
6688baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
668948454079SGustavo F. Padovan 	if (!chan) {
66900a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
66916be36555SAndrei Emeltchenko 		/* Drop packet and return */
66923379013bSDan Carpenter 		kfree_skb(skb);
669313ca56e0SAndrei Emeltchenko 		return;
66940a708f8fSGustavo F. Padovan 	}
66950a708f8fSGustavo F. Padovan 
669649208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
66970a708f8fSGustavo F. Padovan 
6698315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
66995153ceb9SBhaskar Chowdhury 	 * procedure is done simply assume that the channel is supported
6700315917e0SJohan Hedberg 	 * and mark it as ready.
6701315917e0SJohan Hedberg 	 */
6702315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
6703315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
6704315917e0SJohan Hedberg 
670589bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
67060a708f8fSGustavo F. Padovan 		goto drop;
67070a708f8fSGustavo F. Padovan 
67080c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
670938319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
671015f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
671115f02b91SLuiz Augusto von Dentz 		if (l2cap_ecred_data_rcv(chan, skb) < 0)
6712fad5fc89SJohan Hedberg 			goto drop;
6713fad5fc89SJohan Hedberg 
6714fad5fc89SJohan Hedberg 		goto done;
6715fad5fc89SJohan Hedberg 
67160a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
67170a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
67180a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
67190a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
67200a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
67210a708f8fSGustavo F. Padovan 
67222c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
67232c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
67240a708f8fSGustavo F. Padovan 			goto drop;
67252c96e03dSSzymon Janc 		}
67260a708f8fSGustavo F. Padovan 
672780b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
67280a708f8fSGustavo F. Padovan 			goto done;
67290a708f8fSGustavo F. Padovan 		break;
67300a708f8fSGustavo F. Padovan 
67310a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
67320a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6733cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
67340a708f8fSGustavo F. Padovan 		goto done;
67350a708f8fSGustavo F. Padovan 
67360a708f8fSGustavo F. Padovan 	default:
67370c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
67380a708f8fSGustavo F. Padovan 		break;
67390a708f8fSGustavo F. Padovan 	}
67400a708f8fSGustavo F. Padovan 
67410a708f8fSGustavo F. Padovan drop:
67420a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67430a708f8fSGustavo F. Padovan 
67440a708f8fSGustavo F. Padovan done:
67456be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
6746d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
67470a708f8fSGustavo F. Padovan }
67480a708f8fSGustavo F. Padovan 
l2cap_conless_channel(struct l2cap_conn * conn,__le16 psm,struct sk_buff * skb)674984104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
675084104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
67510a708f8fSGustavo F. Padovan {
6752ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
675323691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
67540a708f8fSGustavo F. Padovan 
6755ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
6756a24cce14SJohan Hedberg 		goto free_skb;
6757ae4fd2d3SMarcel Holtmann 
6758bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
6759bf20fd4eSJohan Hedberg 					ACL_LINK);
676023691d75SGustavo F. Padovan 	if (!chan)
6761a24cce14SJohan Hedberg 		goto free_skb;
67620a708f8fSGustavo F. Padovan 
67635b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
67640a708f8fSGustavo F. Padovan 
676589bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
67660a708f8fSGustavo F. Padovan 		goto drop;
67670a708f8fSGustavo F. Padovan 
6768e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
67690a708f8fSGustavo F. Padovan 		goto drop;
67700a708f8fSGustavo F. Padovan 
67712edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
6772a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
6773a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
67742edf870dSMarcel Holtmann 
6775a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
6776a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
677784104b24SAndrei Emeltchenko 		return;
6778a24cce14SJohan Hedberg 	}
67790a708f8fSGustavo F. Padovan 
67800a708f8fSGustavo F. Padovan drop:
6781a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
6782a24cce14SJohan Hedberg free_skb:
67830a708f8fSGustavo F. Padovan 	kfree_skb(skb);
67840a708f8fSGustavo F. Padovan }
67850a708f8fSGustavo F. Padovan 
l2cap_recv_frame(struct l2cap_conn * conn,struct sk_buff * skb)67860a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
67870a708f8fSGustavo F. Padovan {
67880a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
678961a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
67900a708f8fSGustavo F. Padovan 	u16 cid, len;
67910a708f8fSGustavo F. Padovan 	__le16 psm;
67920a708f8fSGustavo F. Padovan 
679361a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
679461a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
679561a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
679661a939c6SJohan Hedberg 		return;
679761a939c6SJohan Hedberg 	}
679861a939c6SJohan Hedberg 
67990a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
68000a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
68010a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
68020a708f8fSGustavo F. Padovan 
68030a708f8fSGustavo F. Padovan 	if (len != skb->len) {
68040a708f8fSGustavo F. Padovan 		kfree_skb(skb);
68050a708f8fSGustavo F. Padovan 		return;
68060a708f8fSGustavo F. Padovan 	}
68070a708f8fSGustavo F. Padovan 
68089e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
68099e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
68109e1d7e15SJohan Hedberg 	 */
68119e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
68123d4f9c00SArchie Pusaka 	    hci_bdaddr_list_lookup(&hcon->hdev->reject_list, &hcon->dst,
6813a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
6814e493150eSJohan Hedberg 		kfree_skb(skb);
6815e493150eSJohan Hedberg 		return;
6816e493150eSJohan Hedberg 	}
6817e493150eSJohan Hedberg 
68180a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
68190a708f8fSGustavo F. Padovan 
68200a708f8fSGustavo F. Padovan 	switch (cid) {
68210a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
68220a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
68230a708f8fSGustavo F. Padovan 		break;
68240a708f8fSGustavo F. Padovan 
68250a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
6826097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
68270181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
68280a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
68290a708f8fSGustavo F. Padovan 		break;
68300a708f8fSGustavo F. Padovan 
6831a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
6832a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
6833a2877629SMarcel Holtmann 		break;
6834a2877629SMarcel Holtmann 
68350a708f8fSGustavo F. Padovan 	default:
68360a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
68370a708f8fSGustavo F. Padovan 		break;
68380a708f8fSGustavo F. Padovan 	}
68390a708f8fSGustavo F. Padovan }
68400a708f8fSGustavo F. Padovan 
process_pending_rx(struct work_struct * work)684161a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
684261a939c6SJohan Hedberg {
684361a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
684461a939c6SJohan Hedberg 					       pending_rx_work);
684561a939c6SJohan Hedberg 	struct sk_buff *skb;
684661a939c6SJohan Hedberg 
684761a939c6SJohan Hedberg 	BT_DBG("");
684861a939c6SJohan Hedberg 
684961a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
685061a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
685161a939c6SJohan Hedberg }
685261a939c6SJohan Hedberg 
l2cap_conn_add(struct hci_conn * hcon)6853162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
6854162b49e7SJohan Hedberg {
6855162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
6856162b49e7SJohan Hedberg 	struct hci_chan *hchan;
6857162b49e7SJohan Hedberg 
6858162b49e7SJohan Hedberg 	if (conn)
6859162b49e7SJohan Hedberg 		return conn;
6860162b49e7SJohan Hedberg 
6861162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
6862162b49e7SJohan Hedberg 	if (!hchan)
6863162b49e7SJohan Hedberg 		return NULL;
6864162b49e7SJohan Hedberg 
686527f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
6866162b49e7SJohan Hedberg 	if (!conn) {
6867162b49e7SJohan Hedberg 		hci_chan_del(hchan);
6868162b49e7SJohan Hedberg 		return NULL;
6869162b49e7SJohan Hedberg 	}
6870162b49e7SJohan Hedberg 
6871162b49e7SJohan Hedberg 	kref_init(&conn->ref);
6872162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
687351bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
6874162b49e7SJohan Hedberg 	conn->hchan = hchan;
6875162b49e7SJohan Hedberg 
6876162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
6877162b49e7SJohan Hedberg 
6878ad3f7986SSungwoo Kim 	conn->mtu = hcon->mtu;
6879162b49e7SJohan Hedberg 	conn->feat_mask = 0;
6880162b49e7SJohan Hedberg 
68810bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
68820bd49fc7SJohan Hedberg 
6883d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
6884f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
6885b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
6886b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
6887b5ae344dSJohan Hedberg 
68885a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
6889162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
6890162b49e7SJohan Hedberg 
6891162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
6892162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
6893162b49e7SJohan Hedberg 
6894162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
6895162b49e7SJohan Hedberg 
689661a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
689761a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
6898b8b23001SLuiz Augusto von Dentz 	INIT_DELAYED_WORK(&conn->id_addr_timer, l2cap_conn_update_id_addr);
689961a939c6SJohan Hedberg 
6900162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
6901162b49e7SJohan Hedberg 
6902162b49e7SJohan Hedberg 	return conn;
6903162b49e7SJohan Hedberg }
6904162b49e7SJohan Hedberg 
is_valid_psm(u16 psm,u8 dst_type)6905149b3f13SMeng Yu static bool is_valid_psm(u16 psm, u8 dst_type)
6906149b3f13SMeng Yu {
6907162b49e7SJohan Hedberg 	if (!psm)
6908162b49e7SJohan Hedberg 		return false;
6909162b49e7SJohan Hedberg 
6910162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
6911162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
6912162b49e7SJohan Hedberg 
6913162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
6914162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
6915162b49e7SJohan Hedberg }
6916162b49e7SJohan Hedberg 
6917da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
6918da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
6919da49b602SLuiz Augusto von Dentz 	struct pid *pid;
6920da49b602SLuiz Augusto von Dentz 	int count;
6921da49b602SLuiz Augusto von Dentz };
6922da49b602SLuiz Augusto von Dentz 
l2cap_chan_by_pid(struct l2cap_chan * chan,void * data)6923da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
6924da49b602SLuiz Augusto von Dentz {
6925da49b602SLuiz Augusto von Dentz 	struct l2cap_chan_data *d = data;
6926da49b602SLuiz Augusto von Dentz 	struct pid *pid;
6927da49b602SLuiz Augusto von Dentz 
6928da49b602SLuiz Augusto von Dentz 	if (chan == d->chan)
6929da49b602SLuiz Augusto von Dentz 		return;
6930da49b602SLuiz Augusto von Dentz 
6931da49b602SLuiz Augusto von Dentz 	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
6932da49b602SLuiz Augusto von Dentz 		return;
6933da49b602SLuiz Augusto von Dentz 
6934da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
6935da49b602SLuiz Augusto von Dentz 
6936da49b602SLuiz Augusto von Dentz 	/* Only count deferred channels with the same PID/PSM */
6937da49b602SLuiz Augusto von Dentz 	if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
6938da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
6939da49b602SLuiz Augusto von Dentz 		return;
6940da49b602SLuiz Augusto von Dentz 
6941da49b602SLuiz Augusto von Dentz 	d->count++;
6942da49b602SLuiz Augusto von Dentz }
6943da49b602SLuiz Augusto von Dentz 
l2cap_chan_connect(struct l2cap_chan * chan,__le16 psm,u16 cid,bdaddr_t * dst,u8 dst_type)6944162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
6945162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
6946162b49e7SJohan Hedberg {
6947162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
6948162b49e7SJohan Hedberg 	struct hci_conn *hcon;
6949162b49e7SJohan Hedberg 	struct hci_dev *hdev;
6950162b49e7SJohan Hedberg 	int err;
6951162b49e7SJohan Hedberg 
695215f02b91SLuiz Augusto von Dentz 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
695315f02b91SLuiz Augusto von Dentz 	       dst, dst_type, __le16_to_cpu(psm), chan->mode);
6954162b49e7SJohan Hedberg 
695539385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
6956162b49e7SJohan Hedberg 	if (!hdev)
6957162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
6958162b49e7SJohan Hedberg 
6959162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
6960162b49e7SJohan Hedberg 
6961162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
6962162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
6963162b49e7SJohan Hedberg 		err = -EINVAL;
6964162b49e7SJohan Hedberg 		goto done;
6965162b49e7SJohan Hedberg 	}
6966162b49e7SJohan Hedberg 
696721626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
696821626e62SJohan Hedberg 		err = -EINVAL;
696921626e62SJohan Hedberg 		goto done;
697021626e62SJohan Hedberg 	}
697121626e62SJohan Hedberg 
697221626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
6973162b49e7SJohan Hedberg 		err = -EINVAL;
6974162b49e7SJohan Hedberg 		goto done;
6975162b49e7SJohan Hedberg 	}
6976162b49e7SJohan Hedberg 
6977162b49e7SJohan Hedberg 	switch (chan->mode) {
6978162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
6979162b49e7SJohan Hedberg 		break;
6980162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
69814be5ca67SLuiz Augusto von Dentz 		break;
698215f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
69834be5ca67SLuiz Augusto von Dentz 		if (!enable_ecred) {
69844be5ca67SLuiz Augusto von Dentz 			err = -EOPNOTSUPP;
69854be5ca67SLuiz Augusto von Dentz 			goto done;
69864be5ca67SLuiz Augusto von Dentz 		}
6987162b49e7SJohan Hedberg 		break;
6988162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
6989162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
6990162b49e7SJohan Hedberg 		if (!disable_ertm)
6991162b49e7SJohan Hedberg 			break;
699219186c7bSGustavo A. R. Silva 		fallthrough;
6993162b49e7SJohan Hedberg 	default:
6994beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
6995162b49e7SJohan Hedberg 		goto done;
6996162b49e7SJohan Hedberg 	}
6997162b49e7SJohan Hedberg 
6998162b49e7SJohan Hedberg 	switch (chan->state) {
6999162b49e7SJohan Hedberg 	case BT_CONNECT:
7000162b49e7SJohan Hedberg 	case BT_CONNECT2:
7001162b49e7SJohan Hedberg 	case BT_CONFIG:
7002162b49e7SJohan Hedberg 		/* Already connecting */
7003162b49e7SJohan Hedberg 		err = 0;
7004162b49e7SJohan Hedberg 		goto done;
7005162b49e7SJohan Hedberg 
7006162b49e7SJohan Hedberg 	case BT_CONNECTED:
7007162b49e7SJohan Hedberg 		/* Already connected */
7008162b49e7SJohan Hedberg 		err = -EISCONN;
7009162b49e7SJohan Hedberg 		goto done;
7010162b49e7SJohan Hedberg 
7011162b49e7SJohan Hedberg 	case BT_OPEN:
7012162b49e7SJohan Hedberg 	case BT_BOUND:
7013162b49e7SJohan Hedberg 		/* Can connect */
7014162b49e7SJohan Hedberg 		break;
7015162b49e7SJohan Hedberg 
7016162b49e7SJohan Hedberg 	default:
7017162b49e7SJohan Hedberg 		err = -EBADFD;
7018162b49e7SJohan Hedberg 		goto done;
7019162b49e7SJohan Hedberg 	}
7020162b49e7SJohan Hedberg 
7021162b49e7SJohan Hedberg 	/* Set destination address and psm */
7022162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
7023162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
7024162b49e7SJohan Hedberg 
7025162b49e7SJohan Hedberg 	chan->psm = psm;
7026162b49e7SJohan Hedberg 	chan->dcid = cid;
7027162b49e7SJohan Hedberg 
70286f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
70296f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
70306f77d8c7SAndre Guedes 		 */
70316f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
70326f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
70336f77d8c7SAndre Guedes 		else
70346f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
70356f77d8c7SAndre Guedes 
7036d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
7037d850bf08SLuiz Augusto von Dentz 			hcon = hci_connect_le(hdev, dst, dst_type, false,
7038fa142220SJakub Pawlowski 					      chan->sec_level,
7039fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
70408e8b92eeSLuiz Augusto von Dentz 					      HCI_ROLE_SLAVE);
70410ad06aa6SJohan Hedberg 		else
70420ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
70430ad06aa6SJohan Hedberg 						   chan->sec_level,
704476b13996SManish Mandlik 						   HCI_LE_CONN_TIMEOUT,
704576b13996SManish Mandlik 						   CONN_REASON_L2CAP_CHAN);
70460ad06aa6SJohan Hedberg 
70476f77d8c7SAndre Guedes 	} else {
7048d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
704976b13996SManish Mandlik 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
705076b13996SManish Mandlik 				       CONN_REASON_L2CAP_CHAN);
70516f77d8c7SAndre Guedes 	}
7052162b49e7SJohan Hedberg 
7053162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
7054162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
7055162b49e7SJohan Hedberg 		goto done;
7056162b49e7SJohan Hedberg 	}
7057162b49e7SJohan Hedberg 
7058162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7059162b49e7SJohan Hedberg 	if (!conn) {
7060162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7061162b49e7SJohan Hedberg 		err = -ENOMEM;
7062162b49e7SJohan Hedberg 		goto done;
7063162b49e7SJohan Hedberg 	}
7064162b49e7SJohan Hedberg 
7065da49b602SLuiz Augusto von Dentz 	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
7066da49b602SLuiz Augusto von Dentz 		struct l2cap_chan_data data;
7067da49b602SLuiz Augusto von Dentz 
7068da49b602SLuiz Augusto von Dentz 		data.chan = chan;
7069da49b602SLuiz Augusto von Dentz 		data.pid = chan->ops->get_peer_pid(chan);
7070da49b602SLuiz Augusto von Dentz 		data.count = 1;
7071da49b602SLuiz Augusto von Dentz 
7072da49b602SLuiz Augusto von Dentz 		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
7073da49b602SLuiz Augusto von Dentz 
7074da49b602SLuiz Augusto von Dentz 		/* Check if there isn't too many channels being connected */
7075da49b602SLuiz Augusto von Dentz 		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
7076da49b602SLuiz Augusto von Dentz 			hci_conn_drop(hcon);
7077da49b602SLuiz Augusto von Dentz 			err = -EPROTO;
7078da49b602SLuiz Augusto von Dentz 			goto done;
7079da49b602SLuiz Augusto von Dentz 		}
7080da49b602SLuiz Augusto von Dentz 	}
7081da49b602SLuiz Augusto von Dentz 
708202e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
708302e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
708402e246aeSJohan Hedberg 
7085162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7086162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7087162b49e7SJohan Hedberg 		err = -EBUSY;
708802e246aeSJohan Hedberg 		goto chan_unlock;
7089162b49e7SJohan Hedberg 	}
7090162b49e7SJohan Hedberg 
7091162b49e7SJohan Hedberg 	/* Update source addr of the socket */
7092162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
7093a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
7094162b49e7SJohan Hedberg 
709502e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
7096162b49e7SJohan Hedberg 
7097162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
7098162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
7099162b49e7SJohan Hedberg 
7100162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
7101162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7102162b49e7SJohan Hedberg 
710361202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
710461202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
710561202e4dSJohan Hedberg 	 */
710661202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
710761202e4dSJohan Hedberg 	chan->sport = 0;
710861202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
710961202e4dSJohan Hedberg 
7110162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
7111162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7112162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
7113e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
7114162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
7115162b49e7SJohan Hedberg 		} else
7116162b49e7SJohan Hedberg 			l2cap_do_start(chan);
7117162b49e7SJohan Hedberg 	}
7118162b49e7SJohan Hedberg 
7119162b49e7SJohan Hedberg 	err = 0;
7120162b49e7SJohan Hedberg 
712102e246aeSJohan Hedberg chan_unlock:
7122162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
712302e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
712402e246aeSJohan Hedberg done:
7125162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
7126162b49e7SJohan Hedberg 	hci_dev_put(hdev);
7127162b49e7SJohan Hedberg 	return err;
7128162b49e7SJohan Hedberg }
71296b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7130162b49e7SJohan Hedberg 
l2cap_ecred_reconfigure(struct l2cap_chan * chan)713115f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
713215f02b91SLuiz Augusto von Dentz {
713315f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
713415f02b91SLuiz Augusto von Dentz 	struct {
713515f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_reconf_req req;
713615f02b91SLuiz Augusto von Dentz 		__le16 scid;
713715f02b91SLuiz Augusto von Dentz 	} pdu;
713815f02b91SLuiz Augusto von Dentz 
713915f02b91SLuiz Augusto von Dentz 	pdu.req.mtu = cpu_to_le16(chan->imtu);
714015f02b91SLuiz Augusto von Dentz 	pdu.req.mps = cpu_to_le16(chan->mps);
714115f02b91SLuiz Augusto von Dentz 	pdu.scid    = cpu_to_le16(chan->scid);
714215f02b91SLuiz Augusto von Dentz 
714315f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
714415f02b91SLuiz Augusto von Dentz 
714515f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
714615f02b91SLuiz Augusto von Dentz 		       sizeof(pdu), &pdu);
714715f02b91SLuiz Augusto von Dentz }
714815f02b91SLuiz Augusto von Dentz 
l2cap_chan_reconfigure(struct l2cap_chan * chan,__u16 mtu)714915f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
715015f02b91SLuiz Augusto von Dentz {
715115f02b91SLuiz Augusto von Dentz 	if (chan->imtu > mtu)
715215f02b91SLuiz Augusto von Dentz 		return -EINVAL;
715315f02b91SLuiz Augusto von Dentz 
715415f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
715515f02b91SLuiz Augusto von Dentz 
715615f02b91SLuiz Augusto von Dentz 	chan->imtu = mtu;
715715f02b91SLuiz Augusto von Dentz 
715815f02b91SLuiz Augusto von Dentz 	l2cap_ecred_reconfigure(chan);
715915f02b91SLuiz Augusto von Dentz 
716015f02b91SLuiz Augusto von Dentz 	return 0;
716115f02b91SLuiz Augusto von Dentz }
716215f02b91SLuiz Augusto von Dentz 
71630a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
71640a708f8fSGustavo F. Padovan 
l2cap_connect_ind(struct hci_dev * hdev,bdaddr_t * bdaddr)7165686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
71660a708f8fSGustavo F. Padovan {
71670a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
716823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
71690a708f8fSGustavo F. Padovan 
71706ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
71710a708f8fSGustavo F. Padovan 
71720a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
717323691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
717423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
717589bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
71760a708f8fSGustavo F. Padovan 			continue;
71770a708f8fSGustavo F. Padovan 
71787eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
71790a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
718043bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71810a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
71820a708f8fSGustavo F. Padovan 			exact++;
71837eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
71840a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
718543bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71860a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
71870a708f8fSGustavo F. Padovan 		}
71880a708f8fSGustavo F. Padovan 	}
718923691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
71900a708f8fSGustavo F. Padovan 
71910a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
71920a708f8fSGustavo F. Padovan }
71930a708f8fSGustavo F. Padovan 
7194e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
7195e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
7196e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
7197e760ec12SJohan Hedberg  */
l2cap_global_fixed_chan(struct l2cap_chan * c,struct hci_conn * hcon)7198e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
7199327a7191SJohan Hedberg 						  struct hci_conn *hcon)
7200e760ec12SJohan Hedberg {
7201327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
7202327a7191SJohan Hedberg 
7203e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
7204e760ec12SJohan Hedberg 
7205e760ec12SJohan Hedberg 	if (c)
7206e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
7207e760ec12SJohan Hedberg 	else
7208e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
7209e760ec12SJohan Hedberg 
7210e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
7211e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
7212e760ec12SJohan Hedberg 			continue;
7213e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
7214e760ec12SJohan Hedberg 			continue;
7215327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
7216e760ec12SJohan Hedberg 			continue;
7217327a7191SJohan Hedberg 		if (src_type != c->src_type)
721854a1b626SJohan Hedberg 			continue;
7219e760ec12SJohan Hedberg 
7220d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
7221e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
7222e760ec12SJohan Hedberg 		return c;
7223e760ec12SJohan Hedberg 	}
7224e760ec12SJohan Hedberg 
7225e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
7226e760ec12SJohan Hedberg 
7227e760ec12SJohan Hedberg 	return NULL;
7228e760ec12SJohan Hedberg }
7229e760ec12SJohan Hedberg 
l2cap_connect_cfm(struct hci_conn * hcon,u8 status)7230539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
72310a708f8fSGustavo F. Padovan {
7232e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
72330a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
7234e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
7235e760ec12SJohan Hedberg 	u8 dst_type;
72360a708f8fSGustavo F. Padovan 
7237539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7238539c496dSJohan Hedberg 		return;
7239539c496dSJohan Hedberg 
72406ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
72410a708f8fSGustavo F. Padovan 
7242dc0f5088SJohan Hedberg 	if (status) {
7243e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7244dc0f5088SJohan Hedberg 		return;
7245ba6fc317SAndrei Emeltchenko 	}
7246dc0f5088SJohan Hedberg 
7247dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7248dc0f5088SJohan Hedberg 	if (!conn)
7249dc0f5088SJohan Hedberg 		return;
7250dc0f5088SJohan Hedberg 
7251a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
7252e760ec12SJohan Hedberg 
7253e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
72543d4f9c00SArchie Pusaka 	if (hci_bdaddr_list_lookup(&hdev->reject_list, &hcon->dst, dst_type))
7255e760ec12SJohan Hedberg 		return;
7256e760ec12SJohan Hedberg 
7257e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
7258e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
7259e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
7260e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
7261e760ec12SJohan Hedberg 	 */
7262327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
7263e760ec12SJohan Hedberg 	while (pchan) {
7264e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
7265e760ec12SJohan Hedberg 
7266e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
7267e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
7268e760ec12SJohan Hedberg 			goto next;
7269e760ec12SJohan Hedberg 
7270e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
7271e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
7272e760ec12SJohan Hedberg 		if (chan) {
7273e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
7274e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
7275a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
7276e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
7277e760ec12SJohan Hedberg 
7278e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
7279e760ec12SJohan Hedberg 		}
7280e760ec12SJohan Hedberg 
7281e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
7282e760ec12SJohan Hedberg next:
7283327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
7284e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
7285e760ec12SJohan Hedberg 		pchan = next;
7286e760ec12SJohan Hedberg 	}
7287e760ec12SJohan Hedberg 
7288dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
72890a708f8fSGustavo F. Padovan }
72900a708f8fSGustavo F. Padovan 
l2cap_disconn_ind(struct hci_conn * hcon)7291686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
72920a708f8fSGustavo F. Padovan {
72930a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
72940a708f8fSGustavo F. Padovan 
72950a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
72960a708f8fSGustavo F. Padovan 
7297686ebf28SUlisses Furquim 	if (!conn)
72989f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
72990a708f8fSGustavo F. Padovan 	return conn->disc_reason;
73000a708f8fSGustavo F. Padovan }
73010a708f8fSGustavo F. Padovan 
l2cap_disconn_cfm(struct hci_conn * hcon,u8 reason)73023a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
73030a708f8fSGustavo F. Padovan {
73043a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
73053a6d576bSJohan Hedberg 		return;
73063a6d576bSJohan Hedberg 
73070a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
73080a708f8fSGustavo F. Padovan 
7309e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
73100a708f8fSGustavo F. Padovan }
73110a708f8fSGustavo F. Padovan 
l2cap_check_encryption(struct l2cap_chan * chan,u8 encrypt)73124343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
73130a708f8fSGustavo F. Padovan {
7314715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
73150a708f8fSGustavo F. Padovan 		return;
73160a708f8fSGustavo F. Padovan 
73170a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
73184343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7319ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
73207d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
73217d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
73220f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
73230a708f8fSGustavo F. Padovan 	} else {
73244343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7325c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
73260a708f8fSGustavo F. Padovan 	}
73270a708f8fSGustavo F. Padovan }
73280a708f8fSGustavo F. Padovan 
l2cap_security_cfm(struct hci_conn * hcon,u8 status,u8 encrypt)7329354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
73300a708f8fSGustavo F. Padovan {
73310a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
733248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
73330a708f8fSGustavo F. Padovan 
73340a708f8fSGustavo F. Padovan 	if (!conn)
7335354fe804SJohan Hedberg 		return;
73360a708f8fSGustavo F. Padovan 
733789d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
73380a708f8fSGustavo F. Padovan 
73393df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
73400a708f8fSGustavo F. Padovan 
73413df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
73426be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
73430a708f8fSGustavo F. Padovan 
734489d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
734589d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7346f1cb9af5SVinicius Costa Gomes 
7347191eb398SJohan Hedberg 		if (!status && encrypt)
7348f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
7349f1cb9af5SVinicius Costa Gomes 
735096eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
73516be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
73520a708f8fSGustavo F. Padovan 			continue;
73530a708f8fSGustavo F. Padovan 		}
73540a708f8fSGustavo F. Padovan 
735589bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
735689bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7357d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
73584343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
73596be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
73600a708f8fSGustavo F. Padovan 			continue;
73610a708f8fSGustavo F. Padovan 		}
73620a708f8fSGustavo F. Padovan 
736389bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
7364693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
736593c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
73666d3c15daSJohan Hedberg 			else
7367ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7368fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
736915f02b91SLuiz Augusto von Dentz 			   !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
737015f02b91SLuiz Augusto von Dentz 			     chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
73710a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7372df3c3931SJohan Hedberg 			__u16 res, stat;
73730a708f8fSGustavo F. Padovan 
7374693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
7375bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7376df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7377df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
73782dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7379df3c3931SJohan Hedberg 				} else {
7380acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7381df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7382df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7383df3c3931SJohan Hedberg 				}
73840a708f8fSGustavo F. Padovan 			} else {
7385acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7386ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7387df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7388df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
73890a708f8fSGustavo F. Padovan 			}
73900a708f8fSGustavo F. Padovan 
7391fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7392fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7393df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7394df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7395fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7396fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
73972d369359SMat Martineau 
73982d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
73992d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
74002d369359SMat Martineau 				char buf[128];
74012d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
74022d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
74032d369359SMat Martineau 					       L2CAP_CONF_REQ,
7404e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
74052d369359SMat Martineau 					       buf);
74062d369359SMat Martineau 				chan->num_conf_req++;
74072d369359SMat Martineau 			}
74080a708f8fSGustavo F. Padovan 		}
74090a708f8fSGustavo F. Padovan 
74106be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
74110a708f8fSGustavo F. Padovan 	}
74120a708f8fSGustavo F. Padovan 
74133df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
74140a708f8fSGustavo F. Padovan }
74150a708f8fSGustavo F. Padovan 
74164d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
l2cap_recv_frag(struct l2cap_conn * conn,struct sk_buff * skb,u16 len)74174d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
74184d7ea8eeSLuiz Augusto von Dentz 			   u16 len)
74194d7ea8eeSLuiz Augusto von Dentz {
74204d7ea8eeSLuiz Augusto von Dentz 	if (!conn->rx_skb) {
74214d7ea8eeSLuiz Augusto von Dentz 		/* Allocate skb for the complete frame (with header) */
74224d7ea8eeSLuiz Augusto von Dentz 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
74234d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb)
74244d7ea8eeSLuiz Augusto von Dentz 			return -ENOMEM;
74254d7ea8eeSLuiz Augusto von Dentz 		/* Init rx_len */
74264d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len;
74274d7ea8eeSLuiz Augusto von Dentz 	}
74284d7ea8eeSLuiz Augusto von Dentz 
74294d7ea8eeSLuiz Augusto von Dentz 	/* Copy as much as the rx_skb can hold */
74304d7ea8eeSLuiz Augusto von Dentz 	len = min_t(u16, len, skb->len);
74314d7ea8eeSLuiz Augusto von Dentz 	skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
74324d7ea8eeSLuiz Augusto von Dentz 	skb_pull(skb, len);
74334d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len -= len;
74344d7ea8eeSLuiz Augusto von Dentz 
74354d7ea8eeSLuiz Augusto von Dentz 	return len;
74364d7ea8eeSLuiz Augusto von Dentz }
74374d7ea8eeSLuiz Augusto von Dentz 
l2cap_recv_len(struct l2cap_conn * conn,struct sk_buff * skb)74384d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
74394d7ea8eeSLuiz Augusto von Dentz {
74404d7ea8eeSLuiz Augusto von Dentz 	struct sk_buff *rx_skb;
74414d7ea8eeSLuiz Augusto von Dentz 	int len;
74424d7ea8eeSLuiz Augusto von Dentz 
74434d7ea8eeSLuiz Augusto von Dentz 	/* Append just enough to complete the header */
74444d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
74454d7ea8eeSLuiz Augusto von Dentz 
74464d7ea8eeSLuiz Augusto von Dentz 	/* If header could not be read just continue */
74474d7ea8eeSLuiz Augusto von Dentz 	if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
74484d7ea8eeSLuiz Augusto von Dentz 		return len;
74494d7ea8eeSLuiz Augusto von Dentz 
74504d7ea8eeSLuiz Augusto von Dentz 	rx_skb = conn->rx_skb;
74514d7ea8eeSLuiz Augusto von Dentz 	len = get_unaligned_le16(rx_skb->data);
74524d7ea8eeSLuiz Augusto von Dentz 
74534d7ea8eeSLuiz Augusto von Dentz 	/* Check if rx_skb has enough space to received all fragments */
74544d7ea8eeSLuiz Augusto von Dentz 	if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
74554d7ea8eeSLuiz Augusto von Dentz 		/* Update expected len */
74564d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
74574d7ea8eeSLuiz Augusto von Dentz 		return L2CAP_LEN_SIZE;
74584d7ea8eeSLuiz Augusto von Dentz 	}
74594d7ea8eeSLuiz Augusto von Dentz 
74604d7ea8eeSLuiz Augusto von Dentz 	/* Reset conn->rx_skb since it will need to be reallocated in order to
74614d7ea8eeSLuiz Augusto von Dentz 	 * fit all fragments.
74624d7ea8eeSLuiz Augusto von Dentz 	 */
74634d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
74644d7ea8eeSLuiz Augusto von Dentz 
74654d7ea8eeSLuiz Augusto von Dentz 	/* Reallocates rx_skb using the exact expected length */
74664d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, rx_skb,
74674d7ea8eeSLuiz Augusto von Dentz 			      len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
74684d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(rx_skb);
74694d7ea8eeSLuiz Augusto von Dentz 
74704d7ea8eeSLuiz Augusto von Dentz 	return len;
74714d7ea8eeSLuiz Augusto von Dentz }
74724d7ea8eeSLuiz Augusto von Dentz 
l2cap_recv_reset(struct l2cap_conn * conn)74734d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
74744d7ea8eeSLuiz Augusto von Dentz {
74754d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(conn->rx_skb);
74764d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
74774d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len = 0;
74784d7ea8eeSLuiz Augusto von Dentz }
74794d7ea8eeSLuiz Augusto von Dentz 
l2cap_recv_acldata(struct hci_conn * hcon,struct sk_buff * skb,u16 flags)74809b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
74810a708f8fSGustavo F. Padovan {
74820a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7483d73a0988SAndrei Emeltchenko 	int len;
74840a708f8fSGustavo F. Padovan 
74850a708f8fSGustavo F. Padovan 	if (!conn)
7486baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
74870a708f8fSGustavo F. Padovan 
74880a708f8fSGustavo F. Padovan 	if (!conn)
74890a708f8fSGustavo F. Padovan 		goto drop;
74900a708f8fSGustavo F. Padovan 
749193917fd2SKai Ye 	BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags);
74920a708f8fSGustavo F. Padovan 
7493d73a0988SAndrei Emeltchenko 	switch (flags) {
7494d73a0988SAndrei Emeltchenko 	case ACL_START:
7495d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7496d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
74974d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb) {
74980a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
74994d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
75000a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
75010a708f8fSGustavo F. Padovan 		}
75020a708f8fSGustavo F. Padovan 
75034d7ea8eeSLuiz Augusto von Dentz 		/* Start fragment may not contain the L2CAP length so just
75044d7ea8eeSLuiz Augusto von Dentz 		 * copy the initial byte when that happens and use conn->mtu as
75054d7ea8eeSLuiz Augusto von Dentz 		 * expected length.
75064d7ea8eeSLuiz Augusto von Dentz 		 */
75074d7ea8eeSLuiz Augusto von Dentz 		if (skb->len < L2CAP_LEN_SIZE) {
75087c9524d9SHawkins Jiawei 			l2cap_recv_frag(conn, skb, conn->mtu);
75097c9524d9SHawkins Jiawei 			break;
75100a708f8fSGustavo F. Padovan 		}
75110a708f8fSGustavo F. Padovan 
75124d7ea8eeSLuiz Augusto von Dentz 		len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
75130a708f8fSGustavo F. Padovan 
75140a708f8fSGustavo F. Padovan 		if (len == skb->len) {
75150a708f8fSGustavo F. Padovan 			/* Complete frame received */
75160a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
75179b4c3336SArron Wang 			return;
75180a708f8fSGustavo F. Padovan 		}
75190a708f8fSGustavo F. Padovan 
752093917fd2SKai Ye 		BT_DBG("Start: total len %d, frag len %u", len, skb->len);
75210a708f8fSGustavo F. Padovan 
75220a708f8fSGustavo F. Padovan 		if (skb->len > len) {
752393917fd2SKai Ye 			BT_ERR("Frame is too long (len %u, expected len %d)",
75240a708f8fSGustavo F. Padovan 			       skb->len, len);
75250a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
75260a708f8fSGustavo F. Padovan 			goto drop;
75270a708f8fSGustavo F. Padovan 		}
75280a708f8fSGustavo F. Padovan 
75294d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
75304d7ea8eeSLuiz Augusto von Dentz 		if (l2cap_recv_frag(conn, skb, len) < 0)
75310a708f8fSGustavo F. Padovan 			goto drop;
75320a708f8fSGustavo F. Padovan 
7533d73a0988SAndrei Emeltchenko 		break;
7534d73a0988SAndrei Emeltchenko 
7535d73a0988SAndrei Emeltchenko 	case ACL_CONT:
753693917fd2SKai Ye 		BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len);
75370a708f8fSGustavo F. Padovan 
75384d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb) {
75390a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
75400a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
75410a708f8fSGustavo F. Padovan 			goto drop;
75420a708f8fSGustavo F. Padovan 		}
75430a708f8fSGustavo F. Padovan 
75444d7ea8eeSLuiz Augusto von Dentz 		/* Complete the L2CAP length if it has not been read */
75454d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
75464d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_len(conn, skb) < 0) {
75470a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
75480a708f8fSGustavo F. Padovan 				goto drop;
75490a708f8fSGustavo F. Padovan 			}
75500a708f8fSGustavo F. Padovan 
75514d7ea8eeSLuiz Augusto von Dentz 			/* Header still could not be read just continue */
75524d7ea8eeSLuiz Augusto von Dentz 			if (conn->rx_skb->len < L2CAP_LEN_SIZE)
75537c9524d9SHawkins Jiawei 				break;
75544d7ea8eeSLuiz Augusto von Dentz 		}
75554d7ea8eeSLuiz Augusto von Dentz 
75564d7ea8eeSLuiz Augusto von Dentz 		if (skb->len > conn->rx_len) {
755793917fd2SKai Ye 			BT_ERR("Fragment is too long (len %u, expected %u)",
75584d7ea8eeSLuiz Augusto von Dentz 			       skb->len, conn->rx_len);
75594d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
75604d7ea8eeSLuiz Augusto von Dentz 			l2cap_conn_unreliable(conn, ECOMM);
75614d7ea8eeSLuiz Augusto von Dentz 			goto drop;
75624d7ea8eeSLuiz Augusto von Dentz 		}
75634d7ea8eeSLuiz Augusto von Dentz 
75644d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
75654d7ea8eeSLuiz Augusto von Dentz 		l2cap_recv_frag(conn, skb, skb->len);
75660a708f8fSGustavo F. Padovan 
75670a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7568c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7569c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7570c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7571c4e5bafaSJohan Hedberg 			 */
7572c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
75730a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7574c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
75750a708f8fSGustavo F. Padovan 		}
7576d73a0988SAndrei Emeltchenko 		break;
75770a708f8fSGustavo F. Padovan 	}
75780a708f8fSGustavo F. Padovan 
75790a708f8fSGustavo F. Padovan drop:
75800a708f8fSGustavo F. Padovan 	kfree_skb(skb);
75810a708f8fSGustavo F. Padovan }
75820a708f8fSGustavo F. Padovan 
7583354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
7584354fe804SJohan Hedberg 	.name		= "L2CAP",
7585539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
75863a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
7587354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
7588354fe804SJohan Hedberg };
7589354fe804SJohan Hedberg 
l2cap_debugfs_show(struct seq_file * f,void * p)75900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
75910a708f8fSGustavo F. Padovan {
759223691d75SGustavo F. Padovan 	struct l2cap_chan *c;
75930a708f8fSGustavo F. Padovan 
7594333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
75950a708f8fSGustavo F. Padovan 
759623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7597eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
7598eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
759989bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
760023691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
760123691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
76020a708f8fSGustavo F. Padovan 	}
76030a708f8fSGustavo F. Padovan 
7604333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
76050a708f8fSGustavo F. Padovan 
76060a708f8fSGustavo F. Padovan 	return 0;
76070a708f8fSGustavo F. Padovan }
76080a708f8fSGustavo F. Padovan 
76098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
76100a708f8fSGustavo F. Padovan 
76110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
76120a708f8fSGustavo F. Padovan 
l2cap_init(void)761364274518SGustavo F. Padovan int __init l2cap_init(void)
76140a708f8fSGustavo F. Padovan {
76150a708f8fSGustavo F. Padovan 	int err;
76160a708f8fSGustavo F. Padovan 
7617bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
76180a708f8fSGustavo F. Padovan 	if (err < 0)
76190a708f8fSGustavo F. Padovan 		return err;
76200a708f8fSGustavo F. Padovan 
7621354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
7622354fe804SJohan Hedberg 
76231120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
76241120e4bfSMarcel Holtmann 		return 0;
76251120e4bfSMarcel Holtmann 
76262d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
76272d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
76280a708f8fSGustavo F. Padovan 
76290a708f8fSGustavo F. Padovan 	return 0;
76300a708f8fSGustavo F. Padovan }
76310a708f8fSGustavo F. Padovan 
l2cap_exit(void)763264274518SGustavo F. Padovan void l2cap_exit(void)
76330a708f8fSGustavo F. Padovan {
76340a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7635354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
7636bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
76370a708f8fSGustavo F. Padovan }
76380a708f8fSGustavo F. Padovan 
76390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
76400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
76414be5ca67SLuiz Augusto von Dentz 
76424be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
76434be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
7644