xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 61386cba)
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
70a708f8fSGustavo F. Padovan 
80a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
90a708f8fSGustavo F. Padovan 
100a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
110a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
120a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
130a708f8fSGustavo F. Padovan 
140a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
150a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
170a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
180a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
190a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
200a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
210a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
220a708f8fSGustavo F. Padovan 
230a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
240a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
250a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
260a708f8fSGustavo F. Padovan */
270a708f8fSGustavo F. Padovan 
28bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
290a708f8fSGustavo F. Padovan 
300a708f8fSGustavo F. Padovan #include <linux/module.h>
310a708f8fSGustavo F. Padovan 
320a708f8fSGustavo F. Padovan #include <linux/types.h>
330a708f8fSGustavo F. Padovan #include <linux/capability.h>
340a708f8fSGustavo F. Padovan #include <linux/errno.h>
350a708f8fSGustavo F. Padovan #include <linux/kernel.h>
360a708f8fSGustavo F. Padovan #include <linux/sched.h>
370a708f8fSGustavo F. Padovan #include <linux/slab.h>
380a708f8fSGustavo F. Padovan #include <linux/poll.h>
390a708f8fSGustavo F. Padovan #include <linux/fcntl.h>
400a708f8fSGustavo F. Padovan #include <linux/init.h>
410a708f8fSGustavo F. Padovan #include <linux/interrupt.h>
420a708f8fSGustavo F. Padovan #include <linux/socket.h>
430a708f8fSGustavo F. Padovan #include <linux/skbuff.h>
440a708f8fSGustavo F. Padovan #include <linux/list.h>
450a708f8fSGustavo F. Padovan #include <linux/device.h>
460a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
470a708f8fSGustavo F. Padovan #include <linux/seq_file.h>
480a708f8fSGustavo F. Padovan #include <linux/uaccess.h>
490a708f8fSGustavo F. Padovan #include <linux/crc16.h>
500a708f8fSGustavo F. Padovan #include <net/sock.h>
510a708f8fSGustavo F. Padovan 
520a708f8fSGustavo F. Padovan #include <asm/unaligned.h>
530a708f8fSGustavo F. Padovan 
540a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
550a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
560a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
57b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
580a708f8fSGustavo F. Padovan 
59eb939922SRusty Russell bool disable_ertm;
600a708f8fSGustavo F. Padovan 
610a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
6250a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
630a708f8fSGustavo F. Padovan 
64b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
65b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
660a708f8fSGustavo F. Padovan 
670a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
680a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
694519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
704519de9aSGustavo F. Padovan 								void *data);
71710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
724519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
734519de9aSGustavo F. Padovan 				struct l2cap_chan *chan, int err);
740a708f8fSGustavo F. Padovan 
750a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7671ba0e56SGustavo F. Padovan 
77baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
780a708f8fSGustavo F. Padovan {
793df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
80baa7e1faSGustavo F. Padovan 
813df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
823df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
833df91ea2SAndrei Emeltchenko 			return c;
840a708f8fSGustavo F. Padovan 	}
853df91ea2SAndrei Emeltchenko 	return NULL;
86baa7e1faSGustavo F. Padovan }
870a708f8fSGustavo F. Padovan 
88baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
890a708f8fSGustavo F. Padovan {
903df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
91baa7e1faSGustavo F. Padovan 
923df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
933df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
943df91ea2SAndrei Emeltchenko 			return c;
950a708f8fSGustavo F. Padovan 	}
963df91ea2SAndrei Emeltchenko 	return NULL;
97baa7e1faSGustavo F. Padovan }
980a708f8fSGustavo F. Padovan 
990a708f8fSGustavo F. Padovan /* Find channel with given SCID.
1000a708f8fSGustavo F. Padovan  * Returns locked socket */
101baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1020a708f8fSGustavo F. Padovan {
10348454079SGustavo F. Padovan 	struct l2cap_chan *c;
104baa7e1faSGustavo F. Padovan 
1053df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
106baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
1073df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1083df91ea2SAndrei Emeltchenko 
10948454079SGustavo F. Padovan 	return c;
1100a708f8fSGustavo F. Padovan }
1110a708f8fSGustavo F. Padovan 
112baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1130a708f8fSGustavo F. Padovan {
1143df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
115baa7e1faSGustavo F. Padovan 
1163df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1173df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1183df91ea2SAndrei Emeltchenko 			return c;
1190a708f8fSGustavo F. Padovan 	}
1203df91ea2SAndrei Emeltchenko 	return NULL;
121baa7e1faSGustavo F. Padovan }
1220a708f8fSGustavo F. Padovan 
123baa7e1faSGustavo F. Padovan static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1240a708f8fSGustavo F. Padovan {
12548454079SGustavo F. Padovan 	struct l2cap_chan *c;
126baa7e1faSGustavo F. Padovan 
1273df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
128baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_ident(conn, ident);
1293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1303df91ea2SAndrei Emeltchenko 
13148454079SGustavo F. Padovan 	return c;
1320a708f8fSGustavo F. Padovan }
1330a708f8fSGustavo F. Padovan 
13423691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1359e4425ffSGustavo F. Padovan {
13623691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1379e4425ffSGustavo F. Padovan 
13823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
13923691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
14023691d75SGustavo F. Padovan 			return c;
1419e4425ffSGustavo F. Padovan 	}
142250938cbSSzymon Janc 	return NULL;
143250938cbSSzymon Janc }
1449e4425ffSGustavo F. Padovan 
1459e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1469e4425ffSGustavo F. Padovan {
14773b2ec18SGustavo F. Padovan 	int err;
14873b2ec18SGustavo F. Padovan 
149333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1509e4425ffSGustavo F. Padovan 
15123691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
15273b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
15373b2ec18SGustavo F. Padovan 		goto done;
1549e4425ffSGustavo F. Padovan 	}
1559e4425ffSGustavo F. Padovan 
15673b2ec18SGustavo F. Padovan 	if (psm) {
1579e4425ffSGustavo F. Padovan 		chan->psm = psm;
1589e4425ffSGustavo F. Padovan 		chan->sport = psm;
15973b2ec18SGustavo F. Padovan 		err = 0;
16073b2ec18SGustavo F. Padovan 	} else {
16173b2ec18SGustavo F. Padovan 		u16 p;
1629e4425ffSGustavo F. Padovan 
16373b2ec18SGustavo F. Padovan 		err = -EINVAL;
16473b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
16523691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
16673b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
16773b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
16873b2ec18SGustavo F. Padovan 				err = 0;
16973b2ec18SGustavo F. Padovan 				break;
17073b2ec18SGustavo F. Padovan 			}
17173b2ec18SGustavo F. Padovan 	}
17273b2ec18SGustavo F. Padovan 
17373b2ec18SGustavo F. Padovan done:
174333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
17573b2ec18SGustavo F. Padovan 	return err;
1769e4425ffSGustavo F. Padovan }
1779e4425ffSGustavo F. Padovan 
1789e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1799e4425ffSGustavo F. Padovan {
180333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1819e4425ffSGustavo F. Padovan 
1829e4425ffSGustavo F. Padovan 	chan->scid = scid;
1839e4425ffSGustavo F. Padovan 
184333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1859e4425ffSGustavo F. Padovan 
1869e4425ffSGustavo F. Padovan 	return 0;
1879e4425ffSGustavo F. Padovan }
1889e4425ffSGustavo F. Padovan 
189baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1900a708f8fSGustavo F. Padovan {
1910a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1920a708f8fSGustavo F. Padovan 
1930a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
194baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1950a708f8fSGustavo F. Padovan 			return cid;
1960a708f8fSGustavo F. Padovan 	}
1970a708f8fSGustavo F. Padovan 
1980a708f8fSGustavo F. Padovan 	return 0;
1990a708f8fSGustavo F. Padovan }
2000a708f8fSGustavo F. Padovan 
2010e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
20289bc500eSGustavo F. Padovan {
20342d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
204badaaa00SGustavo F. Padovan 						state_to_string(state));
205badaaa00SGustavo F. Padovan 
20689bc500eSGustavo F. Padovan 	chan->state = state;
20789bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
20889bc500eSGustavo F. Padovan }
20989bc500eSGustavo F. Padovan 
2100e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2110e587be7SAndrei Emeltchenko {
2120e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2130e587be7SAndrei Emeltchenko 
2140e587be7SAndrei Emeltchenko 	lock_sock(sk);
2150e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2160e587be7SAndrei Emeltchenko 	release_sock(sk);
2170e587be7SAndrei Emeltchenko }
2180e587be7SAndrei Emeltchenko 
2192e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2202e0052e4SAndrei Emeltchenko {
2212e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2222e0052e4SAndrei Emeltchenko 
2232e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2242e0052e4SAndrei Emeltchenko }
2252e0052e4SAndrei Emeltchenko 
2262e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2272e0052e4SAndrei Emeltchenko {
2282e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2292e0052e4SAndrei Emeltchenko 
2302e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2312e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2322e0052e4SAndrei Emeltchenko 	release_sock(sk);
2332e0052e4SAndrei Emeltchenko }
2342e0052e4SAndrei Emeltchenko 
235721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
236ab07801dSGustavo F. Padovan {
237721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
238721c4181SGustavo F. Padovan 							chan_timer.work);
2393df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
240ab07801dSGustavo F. Padovan 	int reason;
241ab07801dSGustavo F. Padovan 
242e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
243ab07801dSGustavo F. Padovan 
2443df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2456be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
246ab07801dSGustavo F. Padovan 
24789bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
248ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
24989bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
250ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
251ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
252ab07801dSGustavo F. Padovan 	else
253ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
254ab07801dSGustavo F. Padovan 
2550f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
256ab07801dSGustavo F. Padovan 
2576be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
258ab07801dSGustavo F. Padovan 
259ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
2603df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
2613df91ea2SAndrei Emeltchenko 
262371fd835SUlisses Furquim 	l2cap_chan_put(chan);
263ab07801dSGustavo F. Padovan }
264ab07801dSGustavo F. Padovan 
26523691d75SGustavo F. Padovan struct l2cap_chan *l2cap_chan_create(struct sock *sk)
2660a708f8fSGustavo F. Padovan {
26748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
2680a708f8fSGustavo F. Padovan 
26948454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
27048454079SGustavo F. Padovan 	if (!chan)
27148454079SGustavo F. Padovan 		return NULL;
2720a708f8fSGustavo F. Padovan 
273c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
274c03b355eSAndrei Emeltchenko 
27548454079SGustavo F. Padovan 	chan->sk = sk;
27648454079SGustavo F. Padovan 
277333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
27823691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
279333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
28023691d75SGustavo F. Padovan 
281721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
282ab07801dSGustavo F. Padovan 
28389bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
28489bc500eSGustavo F. Padovan 
28571ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
28671ba0e56SGustavo F. Padovan 
287abc545b8SSzymon Janc 	BT_DBG("sk %p chan %p", sk, chan);
288abc545b8SSzymon Janc 
28948454079SGustavo F. Padovan 	return chan;
2900a708f8fSGustavo F. Padovan }
2910a708f8fSGustavo F. Padovan 
29223691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
2936ff5abbfSGustavo F. Padovan {
294333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
29523691d75SGustavo F. Padovan 	list_del(&chan->global_l);
296333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
29723691d75SGustavo F. Padovan 
298371fd835SUlisses Furquim 	l2cap_chan_put(chan);
2996ff5abbfSGustavo F. Padovan }
3006ff5abbfSGustavo F. Padovan 
301643162a8SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
3020a708f8fSGustavo F. Padovan {
3030a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
304097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
3050a708f8fSGustavo F. Padovan 
3069f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
3070a708f8fSGustavo F. Padovan 
3088c1d787bSGustavo F. Padovan 	chan->conn = conn;
3090a708f8fSGustavo F. Padovan 
3105491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
3115491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
312b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
313b62f328bSVille Tervo 			/* LE connection */
3140c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
315fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
316fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
317b62f328bSVille Tervo 		} else {
3180a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
319fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
3200c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
321b62f328bSVille Tervo 		}
3225491120eSAndrei Emeltchenko 		break;
3235491120eSAndrei Emeltchenko 
3245491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
3250a708f8fSGustavo F. Padovan 		/* Connectionless socket */
326fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
327fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
3280c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
3295491120eSAndrei Emeltchenko 		break;
3305491120eSAndrei Emeltchenko 
3315491120eSAndrei Emeltchenko 	default:
3320a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
333fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
334fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
3350c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
3360a708f8fSGustavo F. Padovan 	}
3370a708f8fSGustavo F. Padovan 
3388f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
3398f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
3408f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
3418f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
3428f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
3438f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
3448f7975b1SAndrei Emeltchenko 
345371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
346baa7e1faSGustavo F. Padovan 
3473df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
348643162a8SAndrei Emeltchenko }
349643162a8SAndrei Emeltchenko 
350643162a8SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
351643162a8SAndrei Emeltchenko {
352643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
353643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
3543df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3550a708f8fSGustavo F. Padovan }
3560a708f8fSGustavo F. Padovan 
3574519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
3580a708f8fSGustavo F. Padovan {
35948454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
3608c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3610a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
3620a708f8fSGustavo F. Padovan 
363c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
3640a708f8fSGustavo F. Padovan 
36549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
3660a708f8fSGustavo F. Padovan 
3670a708f8fSGustavo F. Padovan 	if (conn) {
368baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
3693df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
3703d57dc68SGustavo F. Padovan 
371371fd835SUlisses Furquim 		l2cap_chan_put(chan);
372baa7e1faSGustavo F. Padovan 
3738c1d787bSGustavo F. Padovan 		chan->conn = NULL;
3740a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
3750a708f8fSGustavo F. Padovan 	}
3760a708f8fSGustavo F. Padovan 
3776be36555SAndrei Emeltchenko 	lock_sock(sk);
3786be36555SAndrei Emeltchenko 
3790e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
3800a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
3810a708f8fSGustavo F. Padovan 
3820a708f8fSGustavo F. Padovan 	if (err)
3832e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
3840a708f8fSGustavo F. Padovan 
3850a708f8fSGustavo F. Padovan 	if (parent) {
3860a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
3870a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
3880a708f8fSGustavo F. Padovan 	} else
3890a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
3900a708f8fSGustavo F. Padovan 
3916be36555SAndrei Emeltchenko 	release_sock(sk);
3926be36555SAndrei Emeltchenko 
393c1360a1cSGustavo F. Padovan 	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
394c1360a1cSGustavo F. Padovan 			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
3956ff5abbfSGustavo F. Padovan 		return;
3962ead70b8SGustavo F. Padovan 
39758d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
3980a708f8fSGustavo F. Padovan 
3990c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
4000a708f8fSGustavo F. Padovan 		struct srej_list *l, *tmp;
4010a708f8fSGustavo F. Padovan 
4021a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4031a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
4041a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
4050a708f8fSGustavo F. Padovan 
406f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
4070a708f8fSGustavo F. Padovan 
40839d5a3eeSGustavo F. Padovan 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
4090a708f8fSGustavo F. Padovan 			list_del(&l->list);
4100a708f8fSGustavo F. Padovan 			kfree(l);
4110a708f8fSGustavo F. Padovan 		}
4120a708f8fSGustavo F. Padovan 	}
4130a708f8fSGustavo F. Padovan }
4140a708f8fSGustavo F. Padovan 
4154519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
4164519de9aSGustavo F. Padovan {
4174519de9aSGustavo F. Padovan 	struct sock *sk;
4184519de9aSGustavo F. Padovan 
4194519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
4204519de9aSGustavo F. Padovan 
4214519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
4220f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
423ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
4243df91ea2SAndrei Emeltchenko 
4256be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
426c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
427ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
4286be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
4293df91ea2SAndrei Emeltchenko 
430ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
4310f852724SGustavo F. Padovan 	}
4324519de9aSGustavo F. Padovan }
4334519de9aSGustavo F. Padovan 
4340f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
4354519de9aSGustavo F. Padovan {
4364519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4374519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
4384519de9aSGustavo F. Padovan 
439e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
440e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
4414519de9aSGustavo F. Padovan 
44289bc500eSGustavo F. Padovan 	switch (chan->state) {
4434519de9aSGustavo F. Padovan 	case BT_LISTEN:
4446be36555SAndrei Emeltchenko 		lock_sock(sk);
4454519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
44689bc500eSGustavo F. Padovan 
4470e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
44889bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
4496be36555SAndrei Emeltchenko 		release_sock(sk);
4504519de9aSGustavo F. Padovan 		break;
4514519de9aSGustavo F. Padovan 
4524519de9aSGustavo F. Padovan 	case BT_CONNECTED:
4534519de9aSGustavo F. Padovan 	case BT_CONFIG:
454715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
4554519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
456c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
457c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
4584519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
4594519de9aSGustavo F. Padovan 		} else
4604519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
4614519de9aSGustavo F. Padovan 		break;
4624519de9aSGustavo F. Padovan 
4634519de9aSGustavo F. Padovan 	case BT_CONNECT2:
464715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
4654519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
4664519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4674519de9aSGustavo F. Padovan 			__u16 result;
4684519de9aSGustavo F. Padovan 
4694519de9aSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup)
4704519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
4714519de9aSGustavo F. Padovan 			else
4724519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
47389bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
4744519de9aSGustavo F. Padovan 
4754519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4764519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4774519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
4784519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4794519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4804519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
4814519de9aSGustavo F. Padovan 		}
4824519de9aSGustavo F. Padovan 
4834519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
4844519de9aSGustavo F. Padovan 		break;
4854519de9aSGustavo F. Padovan 
4864519de9aSGustavo F. Padovan 	case BT_CONNECT:
4874519de9aSGustavo F. Padovan 	case BT_DISCONN:
4884519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
4894519de9aSGustavo F. Padovan 		break;
4904519de9aSGustavo F. Padovan 
4914519de9aSGustavo F. Padovan 	default:
4926be36555SAndrei Emeltchenko 		lock_sock(sk);
4934519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
4946be36555SAndrei Emeltchenko 		release_sock(sk);
4954519de9aSGustavo F. Padovan 		break;
4964519de9aSGustavo F. Padovan 	}
4974519de9aSGustavo F. Padovan }
4984519de9aSGustavo F. Padovan 
4994343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
5000a708f8fSGustavo F. Padovan {
501715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
5024343478fSGustavo F. Padovan 		switch (chan->sec_level) {
5030a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
5040a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
5050a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
5060a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
5070a708f8fSGustavo F. Padovan 		default:
5080a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
5090a708f8fSGustavo F. Padovan 		}
510fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
5114343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
5124343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
5130a708f8fSGustavo F. Padovan 
5144343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
5150a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
5160a708f8fSGustavo F. Padovan 		else
5170a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
5180a708f8fSGustavo F. Padovan 	} else {
5194343478fSGustavo F. Padovan 		switch (chan->sec_level) {
5200a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
5210a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
5220a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
5230a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
5240a708f8fSGustavo F. Padovan 		default:
5250a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
5260a708f8fSGustavo F. Padovan 		}
5270a708f8fSGustavo F. Padovan 	}
5280a708f8fSGustavo F. Padovan }
5290a708f8fSGustavo F. Padovan 
5300a708f8fSGustavo F. Padovan /* Service level security */
531d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
5320a708f8fSGustavo F. Padovan {
5338c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5340a708f8fSGustavo F. Padovan 	__u8 auth_type;
5350a708f8fSGustavo F. Padovan 
5364343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
5370a708f8fSGustavo F. Padovan 
5384343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
5390a708f8fSGustavo F. Padovan }
5400a708f8fSGustavo F. Padovan 
541b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
5420a708f8fSGustavo F. Padovan {
5430a708f8fSGustavo F. Padovan 	u8 id;
5440a708f8fSGustavo F. Padovan 
5450a708f8fSGustavo F. Padovan 	/* Get next available identificator.
5460a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
5470a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
5480a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
5490a708f8fSGustavo F. Padovan 	 */
5500a708f8fSGustavo F. Padovan 
551333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
5520a708f8fSGustavo F. Padovan 
5530a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
5540a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
5550a708f8fSGustavo F. Padovan 
5560a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
5570a708f8fSGustavo F. Padovan 
558333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
5590a708f8fSGustavo F. Padovan 
5600a708f8fSGustavo F. Padovan 	return id;
5610a708f8fSGustavo F. Padovan }
5620a708f8fSGustavo F. Padovan 
5634519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
5640a708f8fSGustavo F. Padovan {
5650a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
5660a708f8fSGustavo F. Padovan 	u8 flags;
5670a708f8fSGustavo F. Padovan 
5680a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
5690a708f8fSGustavo F. Padovan 
5700a708f8fSGustavo F. Padovan 	if (!skb)
5710a708f8fSGustavo F. Padovan 		return;
5720a708f8fSGustavo F. Padovan 
5730a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
5740a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
5750a708f8fSGustavo F. Padovan 	else
5760a708f8fSGustavo F. Padovan 		flags = ACL_START;
5770a708f8fSGustavo F. Padovan 
57814b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
5795e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
58014b12d0bSJaikumar Ganesh 
58173d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
5820a708f8fSGustavo F. Padovan }
5830a708f8fSGustavo F. Padovan 
58473d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
58573d80debSLuiz Augusto von Dentz {
58673d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
58773d80debSLuiz Augusto von Dentz 	u16 flags;
58873d80debSLuiz Augusto von Dentz 
58973d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
59073d80debSLuiz Augusto von Dentz 							skb->priority);
59173d80debSLuiz Augusto von Dentz 
59273d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
59373d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
59473d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
59573d80debSLuiz Augusto von Dentz 	else
59673d80debSLuiz Augusto von Dentz 		flags = ACL_START;
59773d80debSLuiz Augusto von Dentz 
59873d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
59973d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
6000a708f8fSGustavo F. Padovan }
6010a708f8fSGustavo F. Padovan 
60288843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
6030a708f8fSGustavo F. Padovan {
6040a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
6050a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
6068c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
607e4ca6d98SAndrei Emeltchenko 	int count, hlen;
6080a708f8fSGustavo F. Padovan 
60989bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
6100a708f8fSGustavo F. Padovan 		return;
6110a708f8fSGustavo F. Padovan 
612e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
613e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
614e4ca6d98SAndrei Emeltchenko 	else
615e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
6160a708f8fSGustavo F. Padovan 
6170a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
61803a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
6190a708f8fSGustavo F. Padovan 
62088843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
6210a708f8fSGustavo F. Padovan 
6220a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, hlen);
623793c2f1cSAndrei Emeltchenko 
624793c2f1cSAndrei Emeltchenko 	control |= __set_sframe(chan);
6250a708f8fSGustavo F. Padovan 
626e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
62703f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
6280a708f8fSGustavo F. Padovan 
629e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
630e3781735SAndrei Emeltchenko 		control |= __set_ctrl_poll(chan);
6310a708f8fSGustavo F. Padovan 
6320a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
6330a708f8fSGustavo F. Padovan 	if (!skb)
6340a708f8fSGustavo F. Padovan 		return;
6350a708f8fSGustavo F. Padovan 
6360a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
6370a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
638fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
63988843ab0SAndrei Emeltchenko 
64088843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
6410a708f8fSGustavo F. Padovan 
64247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
64303a51213SAndrei Emeltchenko 		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
64403a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
6450a708f8fSGustavo F. Padovan 	}
6460a708f8fSGustavo F. Padovan 
64773d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
64873d80debSLuiz Augusto von Dentz 	l2cap_do_send(chan, skb);
6490a708f8fSGustavo F. Padovan }
6500a708f8fSGustavo F. Padovan 
65188843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
6520a708f8fSGustavo F. Padovan {
653e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
654ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
655e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
6560a708f8fSGustavo F. Padovan 	} else
657ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
6580a708f8fSGustavo F. Padovan 
6590b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
6600a708f8fSGustavo F. Padovan 
661525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
6620a708f8fSGustavo F. Padovan }
6630a708f8fSGustavo F. Padovan 
664b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
6650a708f8fSGustavo F. Padovan {
666c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
6670a708f8fSGustavo F. Padovan }
6680a708f8fSGustavo F. Padovan 
6699b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
6709b27f350SAndrei Emeltchenko {
6719b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
6729b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
6739b27f350SAndrei Emeltchenko 
6749b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
6759b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
6769b27f350SAndrei Emeltchenko 
6779b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
6789b27f350SAndrei Emeltchenko 
6799b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
6809b27f350SAndrei Emeltchenko 
6819b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
6829b27f350SAndrei Emeltchenko }
6839b27f350SAndrei Emeltchenko 
684fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
6850a708f8fSGustavo F. Padovan {
6868c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6870a708f8fSGustavo F. Padovan 
6880a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
6890a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
6900a708f8fSGustavo F. Padovan 			return;
6910a708f8fSGustavo F. Padovan 
692d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
6939b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
6949b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
6950a708f8fSGustavo F. Padovan 	} else {
6960a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
6970a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
6980a708f8fSGustavo F. Padovan 
6990a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
7000a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
7010a708f8fSGustavo F. Padovan 
702ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
7030a708f8fSGustavo F. Padovan 
7040a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
7050a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
7060a708f8fSGustavo F. Padovan 	}
7070a708f8fSGustavo F. Padovan }
7080a708f8fSGustavo F. Padovan 
7090a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
7100a708f8fSGustavo F. Padovan {
7110a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
7120a708f8fSGustavo F. Padovan 	if (!disable_ertm)
7130a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
7140a708f8fSGustavo F. Padovan 
7150a708f8fSGustavo F. Padovan 	switch (mode) {
7160a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
7170a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
7180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
7190a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
7200a708f8fSGustavo F. Padovan 	default:
7210a708f8fSGustavo F. Padovan 		return 0x00;
7220a708f8fSGustavo F. Padovan 	}
7230a708f8fSGustavo F. Padovan }
7240a708f8fSGustavo F. Padovan 
7254519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
7260a708f8fSGustavo F. Padovan {
7276be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
7280a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
7290a708f8fSGustavo F. Padovan 
7300a708f8fSGustavo F. Padovan 	if (!conn)
7310a708f8fSGustavo F. Padovan 		return;
7320a708f8fSGustavo F. Padovan 
7330c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
7341a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
7351a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
7361a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
7370a708f8fSGustavo F. Padovan 	}
7380a708f8fSGustavo F. Padovan 
739fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
740fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
7410a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
7420a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
7430a708f8fSGustavo F. Padovan 
7446be36555SAndrei Emeltchenko 	lock_sock(sk);
7450e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
7462e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
7476be36555SAndrei Emeltchenko 	release_sock(sk);
7480a708f8fSGustavo F. Padovan }
7490a708f8fSGustavo F. Padovan 
7500a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
7510a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
7520a708f8fSGustavo F. Padovan {
7533df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
7540a708f8fSGustavo F. Padovan 
7550a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
7560a708f8fSGustavo F. Padovan 
7573df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
7580a708f8fSGustavo F. Padovan 
7593df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
76048454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
761baa7e1faSGustavo F. Padovan 
7626be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
7630a708f8fSGustavo F. Padovan 
764715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7656be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
7660a708f8fSGustavo F. Padovan 			continue;
7670a708f8fSGustavo F. Padovan 		}
7680a708f8fSGustavo F. Padovan 
76989bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
770d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
771b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
7726be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
7730a708f8fSGustavo F. Padovan 				continue;
7740a708f8fSGustavo F. Padovan 			}
7750a708f8fSGustavo F. Padovan 
776c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
777c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
778c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
7790f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
7806be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
7810a708f8fSGustavo F. Padovan 				continue;
7820a708f8fSGustavo F. Padovan 			}
7830a708f8fSGustavo F. Padovan 
7849b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
7850a708f8fSGustavo F. Padovan 
78689bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
7870a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7880a708f8fSGustavo F. Padovan 			char buf[128];
789fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
790fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
7910a708f8fSGustavo F. Padovan 
792d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
7936be36555SAndrei Emeltchenko 				lock_sock(sk);
7940a708f8fSGustavo F. Padovan 				if (bt_sk(sk)->defer_setup) {
7950a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
7960a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
7970a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
79805e9a2f6SIlia Kolomisnky 					if (parent)
7990a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
8000a708f8fSGustavo F. Padovan 
8010a708f8fSGustavo F. Padovan 				} else {
8020e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
8030a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
8040a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
8050a708f8fSGustavo F. Padovan 				}
8066be36555SAndrei Emeltchenko 				release_sock(sk);
8070a708f8fSGustavo F. Padovan 			} else {
8080a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
8090a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
8100a708f8fSGustavo F. Padovan 			}
8110a708f8fSGustavo F. Padovan 
812fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
813fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
8140a708f8fSGustavo F. Padovan 
815c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
8160a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
8176be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
8180a708f8fSGustavo F. Padovan 				continue;
8190a708f8fSGustavo F. Padovan 			}
8200a708f8fSGustavo F. Padovan 
821c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
8220a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
82373ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
82473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
8250a708f8fSGustavo F. Padovan 		}
8260a708f8fSGustavo F. Padovan 
8276be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
8280a708f8fSGustavo F. Padovan 	}
8290a708f8fSGustavo F. Padovan 
8303df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
8310a708f8fSGustavo F. Padovan }
8320a708f8fSGustavo F. Padovan 
833b62f328bSVille Tervo /* Find socket with cid and source bdaddr.
834b62f328bSVille Tervo  * Returns closest match, locked.
835b62f328bSVille Tervo  */
83623691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
837b62f328bSVille Tervo {
83823691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
839b62f328bSVille Tervo 
84023691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
841b62f328bSVille Tervo 
84223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
84323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
844fe4128e0SGustavo F. Padovan 
84589bc500eSGustavo F. Padovan 		if (state && c->state != state)
846b62f328bSVille Tervo 			continue;
847b62f328bSVille Tervo 
84823691d75SGustavo F. Padovan 		if (c->scid == cid) {
849b62f328bSVille Tervo 			/* Exact match. */
85023691d75SGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, src)) {
85123691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
85223691d75SGustavo F. Padovan 				return c;
85323691d75SGustavo F. Padovan 			}
854b62f328bSVille Tervo 
855b62f328bSVille Tervo 			/* Closest match */
856b62f328bSVille Tervo 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
85723691d75SGustavo F. Padovan 				c1 = c;
858b62f328bSVille Tervo 		}
859b62f328bSVille Tervo 	}
860280f294fSGustavo F. Padovan 
86123691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
862b62f328bSVille Tervo 
86323691d75SGustavo F. Padovan 	return c1;
864b62f328bSVille Tervo }
865b62f328bSVille Tervo 
866b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
867b62f328bSVille Tervo {
868c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
86923691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
870b62f328bSVille Tervo 
871b62f328bSVille Tervo 	BT_DBG("");
872b62f328bSVille Tervo 
873b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
87423691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
875b62f328bSVille Tervo 							conn->src);
87623691d75SGustavo F. Padovan 	if (!pchan)
877b62f328bSVille Tervo 		return;
878b62f328bSVille Tervo 
87923691d75SGustavo F. Padovan 	parent = pchan->sk;
88023691d75SGustavo F. Padovan 
881aa2ac881SGustavo F. Padovan 	lock_sock(parent);
88262f3a2cfSGustavo F. Padovan 
883b62f328bSVille Tervo 	/* Check for backlog size */
884b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
885b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
886b62f328bSVille Tervo 		goto clean;
887b62f328bSVille Tervo 	}
888b62f328bSVille Tervo 
88980808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
89080808e43SGustavo F. Padovan 	if (!chan)
891b62f328bSVille Tervo 		goto clean;
892b62f328bSVille Tervo 
89380808e43SGustavo F. Padovan 	sk = chan->sk;
8945d41ce1dSGustavo F. Padovan 
895b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
896b62f328bSVille Tervo 
897b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
898b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
899b62f328bSVille Tervo 
900d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
901d1010240SGustavo F. Padovan 
9023d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
90348454079SGustavo F. Padovan 
904c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
905b62f328bSVille Tervo 
9060e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
907b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
908b62f328bSVille Tervo 
909b62f328bSVille Tervo clean:
910aa2ac881SGustavo F. Padovan 	release_sock(parent);
911b62f328bSVille Tervo }
912b62f328bSVille Tervo 
913cf4cd009SAndrei Emeltchenko static void l2cap_chan_ready(struct l2cap_chan *chan)
914f1cb9af5SVinicius Costa Gomes {
915cf4cd009SAndrei Emeltchenko 	struct sock *sk = chan->sk;
9166be36555SAndrei Emeltchenko 	struct sock *parent;
9176be36555SAndrei Emeltchenko 
9186be36555SAndrei Emeltchenko 	lock_sock(sk);
9196be36555SAndrei Emeltchenko 
9206be36555SAndrei Emeltchenko 	parent = bt_sk(sk)->parent;
921f1cb9af5SVinicius Costa Gomes 
922f1cb9af5SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
923f1cb9af5SVinicius Costa Gomes 
924f1cb9af5SVinicius Costa Gomes 	chan->conf_state = 0;
925f1cb9af5SVinicius Costa Gomes 	__clear_chan_timer(chan);
926f1cb9af5SVinicius Costa Gomes 
9270e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
928f1cb9af5SVinicius Costa Gomes 	sk->sk_state_change(sk);
929f1cb9af5SVinicius Costa Gomes 
930f1cb9af5SVinicius Costa Gomes 	if (parent)
931f1cb9af5SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9326be36555SAndrei Emeltchenko 
9336be36555SAndrei Emeltchenko 	release_sock(sk);
934f1cb9af5SVinicius Costa Gomes }
935f1cb9af5SVinicius Costa Gomes 
9360a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
9370a708f8fSGustavo F. Padovan {
93848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
9390a708f8fSGustavo F. Padovan 
9400a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
9410a708f8fSGustavo F. Padovan 
942b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
943b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
944b62f328bSVille Tervo 
945160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
946160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
947160dc6acSVinicius Costa Gomes 
9483df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
9490a708f8fSGustavo F. Padovan 
9503df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
951baa7e1faSGustavo F. Padovan 
9526be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
9530a708f8fSGustavo F. Padovan 
95463128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
955b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
956cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
957acd7d370SVille Tervo 
95863128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
9596be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
960c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
9616be36555SAndrei Emeltchenko 			lock_sock(sk);
9620e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
9630a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
9646be36555SAndrei Emeltchenko 			release_sock(sk);
965b501d6a1SAnderson Briglia 
96689bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
967fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
9680a708f8fSGustavo F. Padovan 
9696be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
9700a708f8fSGustavo F. Padovan 	}
9710a708f8fSGustavo F. Padovan 
9723df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
9730a708f8fSGustavo F. Padovan }
9740a708f8fSGustavo F. Padovan 
9750a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
9760a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
9770a708f8fSGustavo F. Padovan {
97848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
9790a708f8fSGustavo F. Padovan 
9800a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
9810a708f8fSGustavo F. Padovan 
9823df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
9830a708f8fSGustavo F. Padovan 
9843df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
985ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
9862e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
9870a708f8fSGustavo F. Padovan 	}
9880a708f8fSGustavo F. Padovan 
9893df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
9900a708f8fSGustavo F. Padovan }
9910a708f8fSGustavo F. Padovan 
992f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
9930a708f8fSGustavo F. Padovan {
994f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
995030013d8SGustavo F. Padovan 							info_timer.work);
9960a708f8fSGustavo F. Padovan 
9970a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
9980a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
9990a708f8fSGustavo F. Padovan 
10000a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
10010a708f8fSGustavo F. Padovan }
10020a708f8fSGustavo F. Padovan 
10035d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
10045d3de7dfSVinicius Costa Gomes {
10055d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
10065d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
10075d3de7dfSVinicius Costa Gomes 
10085d3de7dfSVinicius Costa Gomes 	if (!conn)
10095d3de7dfSVinicius Costa Gomes 		return;
10105d3de7dfSVinicius Costa Gomes 
10115d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
10125d3de7dfSVinicius Costa Gomes 
10135d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
10145d3de7dfSVinicius Costa Gomes 
10153df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10163df91ea2SAndrei Emeltchenko 
10175d3de7dfSVinicius Costa Gomes 	/* Kill channels */
10185d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
10196be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10206be36555SAndrei Emeltchenko 
10215d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
10226be36555SAndrei Emeltchenko 
10236be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
10246be36555SAndrei Emeltchenko 
10255d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
10265d3de7dfSVinicius Costa Gomes 	}
10275d3de7dfSVinicius Costa Gomes 
10283df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
10293df91ea2SAndrei Emeltchenko 
103073d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
103173d80debSLuiz Augusto von Dentz 
10325d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1033127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
10345d3de7dfSVinicius Costa Gomes 
103551a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1036127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
10378aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1038d26a2345SVinicius Costa Gomes 	}
10395d3de7dfSVinicius Costa Gomes 
10405d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
10415d3de7dfSVinicius Costa Gomes 	kfree(conn);
10425d3de7dfSVinicius Costa Gomes }
10435d3de7dfSVinicius Costa Gomes 
10446c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
10455d3de7dfSVinicius Costa Gomes {
10466c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
10476c9d42a1SGustavo F. Padovan 						security_timer.work);
10485d3de7dfSVinicius Costa Gomes 
10495d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
10505d3de7dfSVinicius Costa Gomes }
10515d3de7dfSVinicius Costa Gomes 
10520a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
10530a708f8fSGustavo F. Padovan {
10540a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
105573d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
10560a708f8fSGustavo F. Padovan 
10570a708f8fSGustavo F. Padovan 	if (conn || status)
10580a708f8fSGustavo F. Padovan 		return conn;
10590a708f8fSGustavo F. Padovan 
106073d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
106173d80debSLuiz Augusto von Dentz 	if (!hchan)
10620a708f8fSGustavo F. Padovan 		return NULL;
10630a708f8fSGustavo F. Padovan 
106473d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
106573d80debSLuiz Augusto von Dentz 	if (!conn) {
106673d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
106773d80debSLuiz Augusto von Dentz 		return NULL;
106873d80debSLuiz Augusto von Dentz 	}
106973d80debSLuiz Augusto von Dentz 
10700a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
10710a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
107273d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
10730a708f8fSGustavo F. Padovan 
107473d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
10750a708f8fSGustavo F. Padovan 
1076acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1077acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1078acd7d370SVille Tervo 	else
10790a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1080acd7d370SVille Tervo 
10810a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
10820a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
10830a708f8fSGustavo F. Padovan 
10840a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
10850a708f8fSGustavo F. Padovan 
10860a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
10873df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1088baa7e1faSGustavo F. Padovan 
1089baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
10900a708f8fSGustavo F. Padovan 
10915d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
10926c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
10935d3de7dfSVinicius Costa Gomes 	else
1094030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
10950a708f8fSGustavo F. Padovan 
10969f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
10970a708f8fSGustavo F. Padovan 
10980a708f8fSGustavo F. Padovan 	return conn;
10990a708f8fSGustavo F. Padovan }
11000a708f8fSGustavo F. Padovan 
11010a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
11020a708f8fSGustavo F. Padovan 
11030a708f8fSGustavo F. Padovan /* Find socket with psm and source bdaddr.
11040a708f8fSGustavo F. Padovan  * Returns closest match.
11050a708f8fSGustavo F. Padovan  */
110623691d75SGustavo F. Padovan static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
11070a708f8fSGustavo F. Padovan {
110823691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
11090a708f8fSGustavo F. Padovan 
111023691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
11110a708f8fSGustavo F. Padovan 
111223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
111323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1114fe4128e0SGustavo F. Padovan 
111589bc500eSGustavo F. Padovan 		if (state && c->state != state)
11160a708f8fSGustavo F. Padovan 			continue;
11170a708f8fSGustavo F. Padovan 
111823691d75SGustavo F. Padovan 		if (c->psm == psm) {
11190a708f8fSGustavo F. Padovan 			/* Exact match. */
112023691d75SGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, src)) {
1121a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
112223691d75SGustavo F. Padovan 				return c;
112323691d75SGustavo F. Padovan 			}
11240a708f8fSGustavo F. Padovan 
11250a708f8fSGustavo F. Padovan 			/* Closest match */
11260a708f8fSGustavo F. Padovan 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
112723691d75SGustavo F. Padovan 				c1 = c;
11280a708f8fSGustavo F. Padovan 		}
11290a708f8fSGustavo F. Padovan 	}
11300a708f8fSGustavo F. Padovan 
113123691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
11320a708f8fSGustavo F. Padovan 
113323691d75SGustavo F. Padovan 	return c1;
11340a708f8fSGustavo F. Padovan }
11350a708f8fSGustavo F. Padovan 
1136cbe8fed4SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst)
11370a708f8fSGustavo F. Padovan {
11385d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
11390a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
11400a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
11410a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
11420a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
11430a708f8fSGustavo F. Padovan 	__u8 auth_type;
11440a708f8fSGustavo F. Padovan 	int err;
11450a708f8fSGustavo F. Padovan 
11460a708f8fSGustavo F. Padovan 	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
1147097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm));
11480a708f8fSGustavo F. Padovan 
11490a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
11500a708f8fSGustavo F. Padovan 	if (!hdev)
11510a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
11520a708f8fSGustavo F. Padovan 
115309fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
11540a708f8fSGustavo F. Padovan 
11556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
115603a00194SGustavo F. Padovan 
115703a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
115803a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
115903a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
116003a00194SGustavo F. Padovan 		err = -EINVAL;
116103a00194SGustavo F. Padovan 		goto done;
116203a00194SGustavo F. Padovan 	}
116303a00194SGustavo F. Padovan 
116403a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
116503a00194SGustavo F. Padovan 		err = -EINVAL;
116603a00194SGustavo F. Padovan 		goto done;
116703a00194SGustavo F. Padovan 	}
116803a00194SGustavo F. Padovan 
116903a00194SGustavo F. Padovan 	switch (chan->mode) {
117003a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
117103a00194SGustavo F. Padovan 		break;
117203a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
117303a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
117403a00194SGustavo F. Padovan 		if (!disable_ertm)
117503a00194SGustavo F. Padovan 			break;
117603a00194SGustavo F. Padovan 		/* fall through */
117703a00194SGustavo F. Padovan 	default:
117803a00194SGustavo F. Padovan 		err = -ENOTSUPP;
117903a00194SGustavo F. Padovan 		goto done;
118003a00194SGustavo F. Padovan 	}
118103a00194SGustavo F. Padovan 
11826be36555SAndrei Emeltchenko 	lock_sock(sk);
11836be36555SAndrei Emeltchenko 
118403a00194SGustavo F. Padovan 	switch (sk->sk_state) {
118503a00194SGustavo F. Padovan 	case BT_CONNECT:
118603a00194SGustavo F. Padovan 	case BT_CONNECT2:
118703a00194SGustavo F. Padovan 	case BT_CONFIG:
118803a00194SGustavo F. Padovan 		/* Already connecting */
118903a00194SGustavo F. Padovan 		err = 0;
11906be36555SAndrei Emeltchenko 		release_sock(sk);
119103a00194SGustavo F. Padovan 		goto done;
119203a00194SGustavo F. Padovan 
119303a00194SGustavo F. Padovan 	case BT_CONNECTED:
119403a00194SGustavo F. Padovan 		/* Already connected */
119503a00194SGustavo F. Padovan 		err = -EISCONN;
11966be36555SAndrei Emeltchenko 		release_sock(sk);
119703a00194SGustavo F. Padovan 		goto done;
119803a00194SGustavo F. Padovan 
119903a00194SGustavo F. Padovan 	case BT_OPEN:
120003a00194SGustavo F. Padovan 	case BT_BOUND:
120103a00194SGustavo F. Padovan 		/* Can connect */
120203a00194SGustavo F. Padovan 		break;
120303a00194SGustavo F. Padovan 
120403a00194SGustavo F. Padovan 	default:
120503a00194SGustavo F. Padovan 		err = -EBADFD;
12066be36555SAndrei Emeltchenko 		release_sock(sk);
120703a00194SGustavo F. Padovan 		goto done;
120803a00194SGustavo F. Padovan 	}
120903a00194SGustavo F. Padovan 
121003a00194SGustavo F. Padovan 	/* Set destination address and psm */
12119219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
12126be36555SAndrei Emeltchenko 
12136be36555SAndrei Emeltchenko 	release_sock(sk);
12146be36555SAndrei Emeltchenko 
121503a00194SGustavo F. Padovan 	chan->psm = psm;
121603a00194SGustavo F. Padovan 	chan->dcid = cid;
12170a708f8fSGustavo F. Padovan 
12184343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
12190a708f8fSGustavo F. Padovan 
1220fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
1221acd7d370SVille Tervo 		hcon = hci_connect(hdev, LE_LINK, dst,
12224343478fSGustavo F. Padovan 					chan->sec_level, auth_type);
1223acd7d370SVille Tervo 	else
12240a708f8fSGustavo F. Padovan 		hcon = hci_connect(hdev, ACL_LINK, dst,
12254343478fSGustavo F. Padovan 					chan->sec_level, auth_type);
1226acd7d370SVille Tervo 
122730e76272SVille Tervo 	if (IS_ERR(hcon)) {
122830e76272SVille Tervo 		err = PTR_ERR(hcon);
12290a708f8fSGustavo F. Padovan 		goto done;
123030e76272SVille Tervo 	}
12310a708f8fSGustavo F. Padovan 
12320a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
12330a708f8fSGustavo F. Padovan 	if (!conn) {
12340a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
123530e76272SVille Tervo 		err = -ENOMEM;
12360a708f8fSGustavo F. Padovan 		goto done;
12370a708f8fSGustavo F. Padovan 	}
12380a708f8fSGustavo F. Padovan 
12390a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
12400a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
12410a708f8fSGustavo F. Padovan 
12426be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
124348454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
12446be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
124548454079SGustavo F. Padovan 
12466be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1247c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
12480a708f8fSGustavo F. Padovan 
12490a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1250715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1251c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1252d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
12536be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
12540a708f8fSGustavo F. Padovan 		} else
1255fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12560a708f8fSGustavo F. Padovan 	}
12570a708f8fSGustavo F. Padovan 
125830e76272SVille Tervo 	err = 0;
125930e76272SVille Tervo 
12600a708f8fSGustavo F. Padovan done:
12616be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
126209fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
12630a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
12640a708f8fSGustavo F. Padovan 	return err;
12650a708f8fSGustavo F. Padovan }
12660a708f8fSGustavo F. Padovan 
1267dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
12680a708f8fSGustavo F. Padovan {
12698c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
12700a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
12710a708f8fSGustavo F. Padovan 	int err = 0;
12720a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
12730a708f8fSGustavo F. Padovan 
12740a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
12750a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1276a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
12770a708f8fSGustavo F. Padovan 		if (!timeo)
12780a708f8fSGustavo F. Padovan 			timeo = HZ/5;
12790a708f8fSGustavo F. Padovan 
12800a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
12810a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
12820a708f8fSGustavo F. Padovan 			break;
12830a708f8fSGustavo F. Padovan 		}
12840a708f8fSGustavo F. Padovan 
12850a708f8fSGustavo F. Padovan 		release_sock(sk);
12860a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
12870a708f8fSGustavo F. Padovan 		lock_sock(sk);
1288a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
12890a708f8fSGustavo F. Padovan 
12900a708f8fSGustavo F. Padovan 		err = sock_error(sk);
12910a708f8fSGustavo F. Padovan 		if (err)
12920a708f8fSGustavo F. Padovan 			break;
12930a708f8fSGustavo F. Padovan 	}
12940a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
12950a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
12960a708f8fSGustavo F. Padovan 	return err;
12970a708f8fSGustavo F. Padovan }
12980a708f8fSGustavo F. Padovan 
1299721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
13000a708f8fSGustavo F. Padovan {
1301721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1302721c4181SGustavo F. Padovan 							monitor_timer.work);
13030a708f8fSGustavo F. Padovan 
1304525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
13050a708f8fSGustavo F. Padovan 
13066be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
13076be36555SAndrei Emeltchenko 
13082c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
13098c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
13106be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13118d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
13120a708f8fSGustavo F. Padovan 		return;
13130a708f8fSGustavo F. Padovan 	}
13140a708f8fSGustavo F. Padovan 
13156a026610SGustavo F. Padovan 	chan->retry_count++;
13161a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
13170a708f8fSGustavo F. Padovan 
1318525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
13196be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
13208d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
13210a708f8fSGustavo F. Padovan }
13220a708f8fSGustavo F. Padovan 
1323721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
13240a708f8fSGustavo F. Padovan {
1325721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1326721c4181SGustavo F. Padovan 							retrans_timer.work);
13270a708f8fSGustavo F. Padovan 
132849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
13290a708f8fSGustavo F. Padovan 
13306be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
13316be36555SAndrei Emeltchenko 
13326a026610SGustavo F. Padovan 	chan->retry_count = 1;
13331a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
13340a708f8fSGustavo F. Padovan 
1335e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
13360a708f8fSGustavo F. Padovan 
1337525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
13386be36555SAndrei Emeltchenko 
13396be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
13408d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
13410a708f8fSGustavo F. Padovan }
13420a708f8fSGustavo F. Padovan 
134342e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
13440a708f8fSGustavo F. Padovan {
13450a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
13460a708f8fSGustavo F. Padovan 
134758d35f87SGustavo F. Padovan 	while ((skb = skb_peek(&chan->tx_q)) &&
13486a026610SGustavo F. Padovan 			chan->unacked_frames) {
134942e5c802SGustavo F. Padovan 		if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)
13500a708f8fSGustavo F. Padovan 			break;
13510a708f8fSGustavo F. Padovan 
135258d35f87SGustavo F. Padovan 		skb = skb_dequeue(&chan->tx_q);
13530a708f8fSGustavo F. Padovan 		kfree_skb(skb);
13540a708f8fSGustavo F. Padovan 
13556a026610SGustavo F. Padovan 		chan->unacked_frames--;
13560a708f8fSGustavo F. Padovan 	}
13570a708f8fSGustavo F. Padovan 
13586a026610SGustavo F. Padovan 	if (!chan->unacked_frames)
13591a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
13600a708f8fSGustavo F. Padovan }
13610a708f8fSGustavo F. Padovan 
136267c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan)
13630a708f8fSGustavo F. Padovan {
13640a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
136588843ab0SAndrei Emeltchenko 	u32 control;
136688843ab0SAndrei Emeltchenko 	u16 fcs;
13670a708f8fSGustavo F. Padovan 
136858d35f87SGustavo F. Padovan 	while ((skb = skb_dequeue(&chan->tx_q))) {
136988843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
1370fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
137188843ab0SAndrei Emeltchenko 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
13720a708f8fSGustavo F. Padovan 
137347d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
137403a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
137503a51213SAndrei Emeltchenko 						skb->len - L2CAP_FCS_SIZE);
137603a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs,
137703a51213SAndrei Emeltchenko 					skb->data + skb->len - L2CAP_FCS_SIZE);
13780a708f8fSGustavo F. Padovan 		}
13790a708f8fSGustavo F. Padovan 
13804343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
13810a708f8fSGustavo F. Padovan 
1382836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
13830a708f8fSGustavo F. Padovan 	}
13840a708f8fSGustavo F. Padovan }
13850a708f8fSGustavo F. Padovan 
1386fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
13870a708f8fSGustavo F. Padovan {
13880a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
138988843ab0SAndrei Emeltchenko 	u16 fcs;
139088843ab0SAndrei Emeltchenko 	u32 control;
13910a708f8fSGustavo F. Padovan 
139258d35f87SGustavo F. Padovan 	skb = skb_peek(&chan->tx_q);
13930a708f8fSGustavo F. Padovan 	if (!skb)
13940a708f8fSGustavo F. Padovan 		return;
13950a708f8fSGustavo F. Padovan 
1396d1726b6dSSzymon Janc 	while (bt_cb(skb)->tx_seq != tx_seq) {
139758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
13980a708f8fSGustavo F. Padovan 			return;
13990a708f8fSGustavo F. Padovan 
1400d1726b6dSSzymon Janc 		skb = skb_queue_next(&chan->tx_q, skb);
1401d1726b6dSSzymon Janc 	}
14020a708f8fSGustavo F. Padovan 
14032c03a7a4SGustavo F. Padovan 	if (chan->remote_max_tx &&
14042c03a7a4SGustavo F. Padovan 			bt_cb(skb)->retries == chan->remote_max_tx) {
14058c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
14060a708f8fSGustavo F. Padovan 		return;
14070a708f8fSGustavo F. Padovan 	}
14080a708f8fSGustavo F. Padovan 
14090a708f8fSGustavo F. Padovan 	tx_skb = skb_clone(skb, GFP_ATOMIC);
14100a708f8fSGustavo F. Padovan 	bt_cb(skb)->retries++;
141188843ab0SAndrei Emeltchenko 
141288843ab0SAndrei Emeltchenko 	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
14137e0ef6eeSAndrei Emeltchenko 	control &= __get_sar_mask(chan);
14140a708f8fSGustavo F. Padovan 
1415e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
141603f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
14170a708f8fSGustavo F. Padovan 
14180b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
1419fb45de7dSAndrei Emeltchenko 	control |= __set_txseq(chan, tx_seq);
14200a708f8fSGustavo F. Padovan 
142188843ab0SAndrei Emeltchenko 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
14220a708f8fSGustavo F. Padovan 
142347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
142403a51213SAndrei Emeltchenko 		fcs = crc16(0, (u8 *)tx_skb->data,
142503a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
142603a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs,
142703a51213SAndrei Emeltchenko 				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
14280a708f8fSGustavo F. Padovan 	}
14290a708f8fSGustavo F. Padovan 
14304343478fSGustavo F. Padovan 	l2cap_do_send(chan, tx_skb);
14310a708f8fSGustavo F. Padovan }
14320a708f8fSGustavo F. Padovan 
143367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
14340a708f8fSGustavo F. Padovan {
14350a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
143688843ab0SAndrei Emeltchenko 	u16 fcs;
143788843ab0SAndrei Emeltchenko 	u32 control;
14380a708f8fSGustavo F. Padovan 	int nsent = 0;
14390a708f8fSGustavo F. Padovan 
144089bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
14410a708f8fSGustavo F. Padovan 		return -ENOTCONN;
14420a708f8fSGustavo F. Padovan 
144358d35f87SGustavo F. Padovan 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
14440a708f8fSGustavo F. Padovan 
14452c03a7a4SGustavo F. Padovan 		if (chan->remote_max_tx &&
14462c03a7a4SGustavo F. Padovan 				bt_cb(skb)->retries == chan->remote_max_tx) {
14478c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
14480a708f8fSGustavo F. Padovan 			break;
14490a708f8fSGustavo F. Padovan 		}
14500a708f8fSGustavo F. Padovan 
14510a708f8fSGustavo F. Padovan 		tx_skb = skb_clone(skb, GFP_ATOMIC);
14520a708f8fSGustavo F. Padovan 
14530a708f8fSGustavo F. Padovan 		bt_cb(skb)->retries++;
14540a708f8fSGustavo F. Padovan 
145588843ab0SAndrei Emeltchenko 		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
14567e0ef6eeSAndrei Emeltchenko 		control &= __get_sar_mask(chan);
14570a708f8fSGustavo F. Padovan 
1458e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
145903f6715dSAndrei Emeltchenko 			control |= __set_ctrl_final(chan);
1460e2ab4353SGustavo F. Padovan 
14610b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->buffer_seq);
1462fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
14630a708f8fSGustavo F. Padovan 
146488843ab0SAndrei Emeltchenko 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
14650a708f8fSGustavo F. Padovan 
146647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
146703a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
146803a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
146903a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs, skb->data +
147003a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
14710a708f8fSGustavo F. Padovan 		}
14720a708f8fSGustavo F. Padovan 
14734343478fSGustavo F. Padovan 		l2cap_do_send(chan, tx_skb);
14740a708f8fSGustavo F. Padovan 
14751a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
14760a708f8fSGustavo F. Padovan 
147742e5c802SGustavo F. Padovan 		bt_cb(skb)->tx_seq = chan->next_tx_seq;
1478836be934SAndrei Emeltchenko 
1479836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
14800a708f8fSGustavo F. Padovan 
14818ed7a0aeSSzymon Janc 		if (bt_cb(skb)->retries == 1) {
14826a026610SGustavo F. Padovan 			chan->unacked_frames++;
1483930fa4aeSSzymon Janc 
1484930fa4aeSSzymon Janc 			if (!nsent++)
1485930fa4aeSSzymon Janc 				__clear_ack_timer(chan);
14868ed7a0aeSSzymon Janc 		}
148723e9fde2SSuraj Sumangala 
14886a026610SGustavo F. Padovan 		chan->frames_sent++;
14890a708f8fSGustavo F. Padovan 
149058d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
149158d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
14920a708f8fSGustavo F. Padovan 		else
149358d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
14940a708f8fSGustavo F. Padovan 	}
14950a708f8fSGustavo F. Padovan 
14960a708f8fSGustavo F. Padovan 	return nsent;
14970a708f8fSGustavo F. Padovan }
14980a708f8fSGustavo F. Padovan 
1499525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
15000a708f8fSGustavo F. Padovan {
15010a708f8fSGustavo F. Padovan 	int ret;
15020a708f8fSGustavo F. Padovan 
150358d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
150458d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
15050a708f8fSGustavo F. Padovan 
150642e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1507525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
15080a708f8fSGustavo F. Padovan 	return ret;
15090a708f8fSGustavo F. Padovan }
15100a708f8fSGustavo F. Padovan 
1511b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan)
15120a708f8fSGustavo F. Padovan {
151388843ab0SAndrei Emeltchenko 	u32 control = 0;
15140a708f8fSGustavo F. Padovan 
15150b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
15160a708f8fSGustavo F. Padovan 
1517e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1518ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1519e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1520525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
15210a708f8fSGustavo F. Padovan 		return;
15220a708f8fSGustavo F. Padovan 	}
15230a708f8fSGustavo F. Padovan 
1524525cd185SGustavo F. Padovan 	if (l2cap_ertm_send(chan) > 0)
15250a708f8fSGustavo F. Padovan 		return;
15260a708f8fSGustavo F. Padovan 
1527ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1528525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
15290a708f8fSGustavo F. Padovan }
15300a708f8fSGustavo F. Padovan 
1531b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1532b17e73bbSSzymon Janc {
1533b17e73bbSSzymon Janc 	__clear_ack_timer(chan);
1534b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
1535b17e73bbSSzymon Janc }
1536b17e73bbSSzymon Janc 
1537525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan)
15380a708f8fSGustavo F. Padovan {
15390a708f8fSGustavo F. Padovan 	struct srej_list *tail;
154088843ab0SAndrei Emeltchenko 	u32 control;
15410a708f8fSGustavo F. Padovan 
1542ab784b73SAndrei Emeltchenko 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
154303f6715dSAndrei Emeltchenko 	control |= __set_ctrl_final(chan);
15440a708f8fSGustavo F. Padovan 
154539d5a3eeSGustavo F. Padovan 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
15460b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, tail->tx_seq);
15470a708f8fSGustavo F. Padovan 
1548525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
15490a708f8fSGustavo F. Padovan }
15500a708f8fSGustavo F. Padovan 
155104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
155204124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
155304124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
15540a708f8fSGustavo F. Padovan {
15550952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
15560a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
15570a708f8fSGustavo F. Padovan 	int err, sent = 0;
15580a708f8fSGustavo F. Padovan 
15590a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
15600a708f8fSGustavo F. Padovan 		return -EFAULT;
15610a708f8fSGustavo F. Padovan 
15620a708f8fSGustavo F. Padovan 	sent += count;
15630a708f8fSGustavo F. Padovan 	len  -= count;
15640a708f8fSGustavo F. Padovan 
15650a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
15660a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
15670a708f8fSGustavo F. Padovan 	while (len) {
15680a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
15690a708f8fSGustavo F. Padovan 
15702f7719ceSAndrei Emeltchenko 		*frag = chan->ops->alloc_skb(chan, count,
157104124681SGustavo F. Padovan 					     msg->msg_flags & MSG_DONTWAIT,
157204124681SGustavo F. Padovan 					     &err);
15732f7719ceSAndrei Emeltchenko 
15740a708f8fSGustavo F. Padovan 		if (!*frag)
15750a708f8fSGustavo F. Padovan 			return err;
15760a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
15770a708f8fSGustavo F. Padovan 			return -EFAULT;
15780a708f8fSGustavo F. Padovan 
15795e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
15805e59b791SLuiz Augusto von Dentz 
15810a708f8fSGustavo F. Padovan 		sent += count;
15820a708f8fSGustavo F. Padovan 		len  -= count;
15830a708f8fSGustavo F. Padovan 
15840a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
15850a708f8fSGustavo F. Padovan 	}
15860a708f8fSGustavo F. Padovan 
15870a708f8fSGustavo F. Padovan 	return sent;
15880a708f8fSGustavo F. Padovan }
15890a708f8fSGustavo F. Padovan 
15905e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
15915e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
15925e59b791SLuiz Augusto von Dentz 						u32 priority)
15930a708f8fSGustavo F. Padovan {
15948c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
15950a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
159603a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
15970a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
15980a708f8fSGustavo F. Padovan 
15996d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
16000a708f8fSGustavo F. Padovan 
16010a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
16022f7719ceSAndrei Emeltchenko 
16032f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
16040a708f8fSGustavo F. Padovan 				   msg->msg_flags & MSG_DONTWAIT, &err);
16052f7719ceSAndrei Emeltchenko 
16060a708f8fSGustavo F. Padovan 	if (!skb)
16070a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
16080a708f8fSGustavo F. Padovan 
16095e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
16105e59b791SLuiz Augusto von Dentz 
16110a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
16120a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1613fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
16140a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1615097db76cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, 2));
16160a708f8fSGustavo F. Padovan 
16170952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
16180a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
16190a708f8fSGustavo F. Padovan 		kfree_skb(skb);
16200a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
16210a708f8fSGustavo F. Padovan 	}
16220a708f8fSGustavo F. Padovan 	return skb;
16230a708f8fSGustavo F. Padovan }
16240a708f8fSGustavo F. Padovan 
16255e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
16265e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
16275e59b791SLuiz Augusto von Dentz 						u32 priority)
16280a708f8fSGustavo F. Padovan {
16298c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
16300a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16310a708f8fSGustavo F. Padovan 	int err, count, hlen = L2CAP_HDR_SIZE;
16320a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
16330a708f8fSGustavo F. Padovan 
16346d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
16350a708f8fSGustavo F. Padovan 
16360a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
16372f7719ceSAndrei Emeltchenko 
16382f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
16390a708f8fSGustavo F. Padovan 				   msg->msg_flags & MSG_DONTWAIT, &err);
16402f7719ceSAndrei Emeltchenko 
16410a708f8fSGustavo F. Padovan 	if (!skb)
16420a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
16430a708f8fSGustavo F. Padovan 
16445e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
16455e59b791SLuiz Augusto von Dentz 
16460a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
16470a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1648fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
16490a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
16500a708f8fSGustavo F. Padovan 
16510952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
16520a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
16530a708f8fSGustavo F. Padovan 		kfree_skb(skb);
16540a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
16550a708f8fSGustavo F. Padovan 	}
16560a708f8fSGustavo F. Padovan 	return skb;
16570a708f8fSGustavo F. Padovan }
16580a708f8fSGustavo F. Padovan 
1659ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1660ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
166188843ab0SAndrei Emeltchenko 						u32 control, u16 sdulen)
16620a708f8fSGustavo F. Padovan {
16638c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
16640a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1665e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
16660a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
16670a708f8fSGustavo F. Padovan 
16686d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
16690a708f8fSGustavo F. Padovan 
16700a708f8fSGustavo F. Padovan 	if (!conn)
16710a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
16720a708f8fSGustavo F. Padovan 
1673e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1674e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1675e4ca6d98SAndrei Emeltchenko 	else
1676e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1677e4ca6d98SAndrei Emeltchenko 
16780a708f8fSGustavo F. Padovan 	if (sdulen)
167903a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
16800a708f8fSGustavo F. Padovan 
168147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
168203a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
16830a708f8fSGustavo F. Padovan 
16840a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
16852f7719ceSAndrei Emeltchenko 
16862f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
16870a708f8fSGustavo F. Padovan 					msg->msg_flags & MSG_DONTWAIT, &err);
16882f7719ceSAndrei Emeltchenko 
16890a708f8fSGustavo F. Padovan 	if (!skb)
16900a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
16910a708f8fSGustavo F. Padovan 
16920a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
16930a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1694fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
16950a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
169688843ab0SAndrei Emeltchenko 
169788843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
169888843ab0SAndrei Emeltchenko 
16990a708f8fSGustavo F. Padovan 	if (sdulen)
170003a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
17010a708f8fSGustavo F. Padovan 
17020952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
17030a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
17040a708f8fSGustavo F. Padovan 		kfree_skb(skb);
17050a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
17060a708f8fSGustavo F. Padovan 	}
17070a708f8fSGustavo F. Padovan 
170847d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
170903a51213SAndrei Emeltchenko 		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
17100a708f8fSGustavo F. Padovan 
17110a708f8fSGustavo F. Padovan 	bt_cb(skb)->retries = 0;
17120a708f8fSGustavo F. Padovan 	return skb;
17130a708f8fSGustavo F. Padovan }
17140a708f8fSGustavo F. Padovan 
171567c9e840SSzymon Janc static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
17160a708f8fSGustavo F. Padovan {
17170a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
17180a708f8fSGustavo F. Padovan 	struct sk_buff_head sar_queue;
171988843ab0SAndrei Emeltchenko 	u32 control;
17200a708f8fSGustavo F. Padovan 	size_t size = 0;
17210a708f8fSGustavo F. Padovan 
17220a708f8fSGustavo F. Padovan 	skb_queue_head_init(&sar_queue);
17237e0ef6eeSAndrei Emeltchenko 	control = __set_ctrl_sar(chan, L2CAP_SAR_START);
172447d1ec61SGustavo F. Padovan 	skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
17250a708f8fSGustavo F. Padovan 	if (IS_ERR(skb))
17260a708f8fSGustavo F. Padovan 		return PTR_ERR(skb);
17270a708f8fSGustavo F. Padovan 
17280a708f8fSGustavo F. Padovan 	__skb_queue_tail(&sar_queue, skb);
17292c03a7a4SGustavo F. Padovan 	len -= chan->remote_mps;
17302c03a7a4SGustavo F. Padovan 	size += chan->remote_mps;
17310a708f8fSGustavo F. Padovan 
17320a708f8fSGustavo F. Padovan 	while (len > 0) {
17330a708f8fSGustavo F. Padovan 		size_t buflen;
17340a708f8fSGustavo F. Padovan 
17352c03a7a4SGustavo F. Padovan 		if (len > chan->remote_mps) {
17367e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
17372c03a7a4SGustavo F. Padovan 			buflen = chan->remote_mps;
17380a708f8fSGustavo F. Padovan 		} else {
17397e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_END);
17400a708f8fSGustavo F. Padovan 			buflen = len;
17410a708f8fSGustavo F. Padovan 		}
17420a708f8fSGustavo F. Padovan 
174347d1ec61SGustavo F. Padovan 		skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
17440a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
17450a708f8fSGustavo F. Padovan 			skb_queue_purge(&sar_queue);
17460a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
17470a708f8fSGustavo F. Padovan 		}
17480a708f8fSGustavo F. Padovan 
17490a708f8fSGustavo F. Padovan 		__skb_queue_tail(&sar_queue, skb);
17500a708f8fSGustavo F. Padovan 		len -= buflen;
17510a708f8fSGustavo F. Padovan 		size += buflen;
17520a708f8fSGustavo F. Padovan 	}
175358d35f87SGustavo F. Padovan 	skb_queue_splice_tail(&sar_queue, &chan->tx_q);
175458d35f87SGustavo F. Padovan 	if (chan->tx_send_head == NULL)
175558d35f87SGustavo F. Padovan 		chan->tx_send_head = sar_queue.next;
17560a708f8fSGustavo F. Padovan 
17570a708f8fSGustavo F. Padovan 	return size;
17580a708f8fSGustavo F. Padovan }
17590a708f8fSGustavo F. Padovan 
17605e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
17615e59b791SLuiz Augusto von Dentz 								u32 priority)
17629a91a04aSGustavo F. Padovan {
17639a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
176488843ab0SAndrei Emeltchenko 	u32 control;
17659a91a04aSGustavo F. Padovan 	int err;
17669a91a04aSGustavo F. Padovan 
17679a91a04aSGustavo F. Padovan 	/* Connectionless channel */
1768715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
17695e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
17709a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
17719a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
17729a91a04aSGustavo F. Padovan 
17739a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
17749a91a04aSGustavo F. Padovan 		return len;
17759a91a04aSGustavo F. Padovan 	}
17769a91a04aSGustavo F. Padovan 
17779a91a04aSGustavo F. Padovan 	switch (chan->mode) {
17789a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
17799a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
17809a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
17819a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
17829a91a04aSGustavo F. Padovan 
17839a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
17845e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
17859a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
17869a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
17879a91a04aSGustavo F. Padovan 
17889a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
17899a91a04aSGustavo F. Padovan 		err = len;
17909a91a04aSGustavo F. Padovan 		break;
17919a91a04aSGustavo F. Padovan 
17929a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
17939a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
17949a91a04aSGustavo F. Padovan 		/* Entire SDU fits into one PDU */
17959a91a04aSGustavo F. Padovan 		if (len <= chan->remote_mps) {
17967e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
17979a91a04aSGustavo F. Padovan 			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
17989a91a04aSGustavo F. Padovan 									0);
17999a91a04aSGustavo F. Padovan 			if (IS_ERR(skb))
18009a91a04aSGustavo F. Padovan 				return PTR_ERR(skb);
18019a91a04aSGustavo F. Padovan 
18029a91a04aSGustavo F. Padovan 			__skb_queue_tail(&chan->tx_q, skb);
18039a91a04aSGustavo F. Padovan 
18049a91a04aSGustavo F. Padovan 			if (chan->tx_send_head == NULL)
18059a91a04aSGustavo F. Padovan 				chan->tx_send_head = skb;
18069a91a04aSGustavo F. Padovan 
18079a91a04aSGustavo F. Padovan 		} else {
18089a91a04aSGustavo F. Padovan 			/* Segment SDU into multiples PDUs */
18099a91a04aSGustavo F. Padovan 			err = l2cap_sar_segment_sdu(chan, msg, len);
18109a91a04aSGustavo F. Padovan 			if (err < 0)
18119a91a04aSGustavo F. Padovan 				return err;
18129a91a04aSGustavo F. Padovan 		}
18139a91a04aSGustavo F. Padovan 
18149a91a04aSGustavo F. Padovan 		if (chan->mode == L2CAP_MODE_STREAMING) {
18159a91a04aSGustavo F. Padovan 			l2cap_streaming_send(chan);
18169a91a04aSGustavo F. Padovan 			err = len;
18179a91a04aSGustavo F. Padovan 			break;
18189a91a04aSGustavo F. Padovan 		}
18199a91a04aSGustavo F. Padovan 
1820e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
1821e2ab4353SGustavo F. Padovan 				test_bit(CONN_WAIT_F, &chan->conn_state)) {
18229a91a04aSGustavo F. Padovan 			err = len;
18239a91a04aSGustavo F. Padovan 			break;
18249a91a04aSGustavo F. Padovan 		}
18259a91a04aSGustavo F. Padovan 
18269a91a04aSGustavo F. Padovan 		err = l2cap_ertm_send(chan);
18279a91a04aSGustavo F. Padovan 		if (err >= 0)
18289a91a04aSGustavo F. Padovan 			err = len;
18299a91a04aSGustavo F. Padovan 
18309a91a04aSGustavo F. Padovan 		break;
18319a91a04aSGustavo F. Padovan 
18329a91a04aSGustavo F. Padovan 	default:
18339a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
18349a91a04aSGustavo F. Padovan 		err = -EBADFD;
18359a91a04aSGustavo F. Padovan 	}
18369a91a04aSGustavo F. Padovan 
18379a91a04aSGustavo F. Padovan 	return err;
18389a91a04aSGustavo F. Padovan }
18399a91a04aSGustavo F. Padovan 
18400a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
18410a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
18420a708f8fSGustavo F. Padovan {
18430a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
184448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
18450a708f8fSGustavo F. Padovan 
18460a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
18470a708f8fSGustavo F. Padovan 
18483df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
18493d57dc68SGustavo F. Padovan 
18503df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
185148454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1852715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
18530a708f8fSGustavo F. Padovan 			continue;
18540a708f8fSGustavo F. Padovan 
18550a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
18560a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
18570a708f8fSGustavo F. Padovan 			continue;
18580a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
18590a708f8fSGustavo F. Padovan 		if (!nskb)
18600a708f8fSGustavo F. Padovan 			continue;
18610a708f8fSGustavo F. Padovan 
186223070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
18630a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
18640a708f8fSGustavo F. Padovan 	}
18653d57dc68SGustavo F. Padovan 
18663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
18670a708f8fSGustavo F. Padovan }
18680a708f8fSGustavo F. Padovan 
18690a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
18700a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
18710a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
18720a708f8fSGustavo F. Padovan {
18730a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
18740a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
18750a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18760a708f8fSGustavo F. Padovan 	int len, count;
18770a708f8fSGustavo F. Padovan 
18780a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
18790a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
18800a708f8fSGustavo F. Padovan 
18810a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
18820a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
18830a708f8fSGustavo F. Padovan 
18840a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
18850a708f8fSGustavo F. Padovan 	if (!skb)
18860a708f8fSGustavo F. Padovan 		return NULL;
18870a708f8fSGustavo F. Padovan 
18880a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
18890a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
18903300d9a9SClaudio Takahasi 
18913300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
18923300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
18933300d9a9SClaudio Takahasi 	else
18940a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
18950a708f8fSGustavo F. Padovan 
18960a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
18970a708f8fSGustavo F. Padovan 	cmd->code  = code;
18980a708f8fSGustavo F. Padovan 	cmd->ident = ident;
18990a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
19000a708f8fSGustavo F. Padovan 
19010a708f8fSGustavo F. Padovan 	if (dlen) {
19020a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
19030a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
19040a708f8fSGustavo F. Padovan 		data += count;
19050a708f8fSGustavo F. Padovan 	}
19060a708f8fSGustavo F. Padovan 
19070a708f8fSGustavo F. Padovan 	len -= skb->len;
19080a708f8fSGustavo F. Padovan 
19090a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
19100a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
19110a708f8fSGustavo F. Padovan 	while (len) {
19120a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
19130a708f8fSGustavo F. Padovan 
19140a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
19150a708f8fSGustavo F. Padovan 		if (!*frag)
19160a708f8fSGustavo F. Padovan 			goto fail;
19170a708f8fSGustavo F. Padovan 
19180a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
19190a708f8fSGustavo F. Padovan 
19200a708f8fSGustavo F. Padovan 		len  -= count;
19210a708f8fSGustavo F. Padovan 		data += count;
19220a708f8fSGustavo F. Padovan 
19230a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
19240a708f8fSGustavo F. Padovan 	}
19250a708f8fSGustavo F. Padovan 
19260a708f8fSGustavo F. Padovan 	return skb;
19270a708f8fSGustavo F. Padovan 
19280a708f8fSGustavo F. Padovan fail:
19290a708f8fSGustavo F. Padovan 	kfree_skb(skb);
19300a708f8fSGustavo F. Padovan 	return NULL;
19310a708f8fSGustavo F. Padovan }
19320a708f8fSGustavo F. Padovan 
19330a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
19340a708f8fSGustavo F. Padovan {
19350a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
19360a708f8fSGustavo F. Padovan 	int len;
19370a708f8fSGustavo F. Padovan 
19380a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
19390a708f8fSGustavo F. Padovan 	*ptr += len;
19400a708f8fSGustavo F. Padovan 
19410a708f8fSGustavo F. Padovan 	*type = opt->type;
19420a708f8fSGustavo F. Padovan 	*olen = opt->len;
19430a708f8fSGustavo F. Padovan 
19440a708f8fSGustavo F. Padovan 	switch (opt->len) {
19450a708f8fSGustavo F. Padovan 	case 1:
19460a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
19470a708f8fSGustavo F. Padovan 		break;
19480a708f8fSGustavo F. Padovan 
19490a708f8fSGustavo F. Padovan 	case 2:
19500a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
19510a708f8fSGustavo F. Padovan 		break;
19520a708f8fSGustavo F. Padovan 
19530a708f8fSGustavo F. Padovan 	case 4:
19540a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
19550a708f8fSGustavo F. Padovan 		break;
19560a708f8fSGustavo F. Padovan 
19570a708f8fSGustavo F. Padovan 	default:
19580a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
19590a708f8fSGustavo F. Padovan 		break;
19600a708f8fSGustavo F. Padovan 	}
19610a708f8fSGustavo F. Padovan 
19620a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
19630a708f8fSGustavo F. Padovan 	return len;
19640a708f8fSGustavo F. Padovan }
19650a708f8fSGustavo F. Padovan 
19660a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
19670a708f8fSGustavo F. Padovan {
19680a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
19690a708f8fSGustavo F. Padovan 
19700a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
19710a708f8fSGustavo F. Padovan 
19720a708f8fSGustavo F. Padovan 	opt->type = type;
19730a708f8fSGustavo F. Padovan 	opt->len  = len;
19740a708f8fSGustavo F. Padovan 
19750a708f8fSGustavo F. Padovan 	switch (len) {
19760a708f8fSGustavo F. Padovan 	case 1:
19770a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
19780a708f8fSGustavo F. Padovan 		break;
19790a708f8fSGustavo F. Padovan 
19800a708f8fSGustavo F. Padovan 	case 2:
19810a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
19820a708f8fSGustavo F. Padovan 		break;
19830a708f8fSGustavo F. Padovan 
19840a708f8fSGustavo F. Padovan 	case 4:
19850a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
19860a708f8fSGustavo F. Padovan 		break;
19870a708f8fSGustavo F. Padovan 
19880a708f8fSGustavo F. Padovan 	default:
19890a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
19900a708f8fSGustavo F. Padovan 		break;
19910a708f8fSGustavo F. Padovan 	}
19920a708f8fSGustavo F. Padovan 
19930a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
19940a708f8fSGustavo F. Padovan }
19950a708f8fSGustavo F. Padovan 
1996f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
1997f89cef09SAndrei Emeltchenko {
1998f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
1999f89cef09SAndrei Emeltchenko 
2000f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2001f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2002f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2003f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2004f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2005f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2006f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2007f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2008f89cef09SAndrei Emeltchenko 		break;
2009f89cef09SAndrei Emeltchenko 
2010f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2011f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2012f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2013f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2014f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2015f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2016f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2017f89cef09SAndrei Emeltchenko 		break;
2018f89cef09SAndrei Emeltchenko 
2019f89cef09SAndrei Emeltchenko 	default:
2020f89cef09SAndrei Emeltchenko 		return;
2021f89cef09SAndrei Emeltchenko 	}
2022f89cef09SAndrei Emeltchenko 
2023f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2024f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2025f89cef09SAndrei Emeltchenko }
2026f89cef09SAndrei Emeltchenko 
2027721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
20280a708f8fSGustavo F. Padovan {
2029721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2030721c4181SGustavo F. Padovan 							ack_timer.work);
20310a708f8fSGustavo F. Padovan 
20322fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
20332fb9b3d4SGustavo F. Padovan 
20346be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20356be36555SAndrei Emeltchenko 
2036b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
20376be36555SAndrei Emeltchenko 
20386be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
203909bfb2eeSSzymon Janc 
204009bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
20410a708f8fSGustavo F. Padovan }
20420a708f8fSGustavo F. Padovan 
2043525cd185SGustavo F. Padovan static inline void l2cap_ertm_init(struct l2cap_chan *chan)
20440a708f8fSGustavo F. Padovan {
204542e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
20466a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
204742e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
20486a026610SGustavo F. Padovan 	chan->num_acked = 0;
20496a026610SGustavo F. Padovan 	chan->frames_sent = 0;
20500a708f8fSGustavo F. Padovan 
2051721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2052721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2053721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
20540a708f8fSGustavo F. Padovan 
2055f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
20560a708f8fSGustavo F. Padovan 
205739d5a3eeSGustavo F. Padovan 	INIT_LIST_HEAD(&chan->srej_l);
20580a708f8fSGustavo F. Padovan }
20590a708f8fSGustavo F. Padovan 
20600a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
20610a708f8fSGustavo F. Padovan {
20620a708f8fSGustavo F. Padovan 	switch (mode) {
20630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
20640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20650a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
20660a708f8fSGustavo F. Padovan 			return mode;
20670a708f8fSGustavo F. Padovan 		/* fall through */
20680a708f8fSGustavo F. Padovan 	default:
20690a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
20700a708f8fSGustavo F. Padovan 	}
20710a708f8fSGustavo F. Padovan }
20720a708f8fSGustavo F. Padovan 
20736327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
20746327eb98SAndrei Emeltchenko {
20756327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
20766327eb98SAndrei Emeltchenko }
20776327eb98SAndrei Emeltchenko 
2078f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2079f89cef09SAndrei Emeltchenko {
2080f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2081f89cef09SAndrei Emeltchenko }
2082f89cef09SAndrei Emeltchenko 
20836327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
20846327eb98SAndrei Emeltchenko {
20856327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2086836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
20876327eb98SAndrei Emeltchenko 		/* use extended control field */
20886327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2089836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2090836be934SAndrei Emeltchenko 	} else {
20916327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
20926327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2093836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2094836be934SAndrei Emeltchenko 	}
20956327eb98SAndrei Emeltchenko }
20966327eb98SAndrei Emeltchenko 
2097710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
20980a708f8fSGustavo F. Padovan {
20990a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
21000c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
21010a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2102c8f79162SAndrei Emeltchenko 	u16 size;
21030a708f8fSGustavo F. Padovan 
210449208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
21050a708f8fSGustavo F. Padovan 
210673ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
21070a708f8fSGustavo F. Padovan 		goto done;
21080a708f8fSGustavo F. Padovan 
21090c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
21100a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
21110a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2112c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
21130a708f8fSGustavo F. Padovan 			break;
21140a708f8fSGustavo F. Padovan 
2115f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2116f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2117f89cef09SAndrei Emeltchenko 
21180a708f8fSGustavo F. Padovan 		/* fall through */
21190a708f8fSGustavo F. Padovan 	default:
21208c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
21210a708f8fSGustavo F. Padovan 		break;
21220a708f8fSGustavo F. Padovan 	}
21230a708f8fSGustavo F. Padovan 
21240a708f8fSGustavo F. Padovan done:
21250c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
21260c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
21270a708f8fSGustavo F. Padovan 
21280c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
21290a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
21308c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
21318c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
21320a708f8fSGustavo F. Padovan 			break;
21330a708f8fSGustavo F. Padovan 
21340a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
21350a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
21360a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
21370a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
21380a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
21390a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
21400a708f8fSGustavo F. Padovan 
21410a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
21420a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
21430a708f8fSGustavo F. Padovan 		break;
21440a708f8fSGustavo F. Padovan 
21450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
21460a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
214747d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
21480a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
21490a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2150c8f79162SAndrei Emeltchenko 
2151c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2152c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2153c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2154c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2155c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
21560a708f8fSGustavo F. Padovan 
21576327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
21586327eb98SAndrei Emeltchenko 
21596327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
21606327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
21610a708f8fSGustavo F. Padovan 
21620a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
21630a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
21640a708f8fSGustavo F. Padovan 
2165f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2166f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2167f89cef09SAndrei Emeltchenko 
21688c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
21690a708f8fSGustavo F. Padovan 			break;
21700a708f8fSGustavo F. Padovan 
217147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2172c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
217347d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
217447d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
21750a708f8fSGustavo F. Padovan 		}
21766327eb98SAndrei Emeltchenko 
21776327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
21786327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
21796327eb98SAndrei Emeltchenko 								chan->tx_win);
21800a708f8fSGustavo F. Padovan 		break;
21810a708f8fSGustavo F. Padovan 
21820a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
21830a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
21840a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
21850a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
21860a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
21870a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2188c8f79162SAndrei Emeltchenko 
2189c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2190c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2191c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2192c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2193c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
21940a708f8fSGustavo F. Padovan 
21950a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
21960a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
21970a708f8fSGustavo F. Padovan 
2198f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2199f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2200f89cef09SAndrei Emeltchenko 
22018c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
22020a708f8fSGustavo F. Padovan 			break;
22030a708f8fSGustavo F. Padovan 
220447d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2205c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
220647d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
220747d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
22080a708f8fSGustavo F. Padovan 		}
22090a708f8fSGustavo F. Padovan 		break;
22100a708f8fSGustavo F. Padovan 	}
22110a708f8fSGustavo F. Padovan 
2212fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
22130a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
22140a708f8fSGustavo F. Padovan 
22150a708f8fSGustavo F. Padovan 	return ptr - data;
22160a708f8fSGustavo F. Padovan }
22170a708f8fSGustavo F. Padovan 
221873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
22190a708f8fSGustavo F. Padovan {
22200a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
22210a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
222273ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
222373ffa904SGustavo F. Padovan 	int len = chan->conf_len;
22240a708f8fSGustavo F. Padovan 	int type, hint, olen;
22250a708f8fSGustavo F. Padovan 	unsigned long val;
22260a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
222742dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
222842dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
22290a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
22300a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2231c8f79162SAndrei Emeltchenko 	u16 size;
22320a708f8fSGustavo F. Padovan 
223373ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
22340a708f8fSGustavo F. Padovan 
22350a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
22360a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
22370a708f8fSGustavo F. Padovan 
22380a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
22390a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
22400a708f8fSGustavo F. Padovan 
22410a708f8fSGustavo F. Padovan 		switch (type) {
22420a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
22430a708f8fSGustavo F. Padovan 			mtu = val;
22440a708f8fSGustavo F. Padovan 			break;
22450a708f8fSGustavo F. Padovan 
22460a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
22470c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
22480a708f8fSGustavo F. Padovan 			break;
22490a708f8fSGustavo F. Padovan 
22500a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
22510a708f8fSGustavo F. Padovan 			break;
22520a708f8fSGustavo F. Padovan 
22530a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
22540a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
22550a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
22560a708f8fSGustavo F. Padovan 			break;
22570a708f8fSGustavo F. Padovan 
22580a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
22590a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2260c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
226142dceae2SAndrei Emeltchenko 			break;
22620a708f8fSGustavo F. Padovan 
226342dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
226442dceae2SAndrei Emeltchenko 			remote_efs = 1;
226542dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
226642dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
22670a708f8fSGustavo F. Padovan 			break;
22680a708f8fSGustavo F. Padovan 
22696327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
22706327eb98SAndrei Emeltchenko 			if (!enable_hs)
22716327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
22726327eb98SAndrei Emeltchenko 
22736327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
22746327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2275836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
22766327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
22770a708f8fSGustavo F. Padovan 			break;
22780a708f8fSGustavo F. Padovan 
22790a708f8fSGustavo F. Padovan 		default:
22800a708f8fSGustavo F. Padovan 			if (hint)
22810a708f8fSGustavo F. Padovan 				break;
22820a708f8fSGustavo F. Padovan 
22830a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
22840a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
22850a708f8fSGustavo F. Padovan 			break;
22860a708f8fSGustavo F. Padovan 		}
22870a708f8fSGustavo F. Padovan 	}
22880a708f8fSGustavo F. Padovan 
228973ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
22900a708f8fSGustavo F. Padovan 		goto done;
22910a708f8fSGustavo F. Padovan 
22920c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
22930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
22940a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2295c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
22960c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
22978c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
22980a708f8fSGustavo F. Padovan 			break;
22990a708f8fSGustavo F. Padovan 		}
23000a708f8fSGustavo F. Padovan 
230142dceae2SAndrei Emeltchenko 		if (remote_efs) {
230242dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
230342dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
230442dceae2SAndrei Emeltchenko 			else
230542dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
230642dceae2SAndrei Emeltchenko 		}
230742dceae2SAndrei Emeltchenko 
23080c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
23090a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
23100a708f8fSGustavo F. Padovan 
23110a708f8fSGustavo F. Padovan 		break;
23120a708f8fSGustavo F. Padovan 	}
23130a708f8fSGustavo F. Padovan 
23140a708f8fSGustavo F. Padovan done:
23150c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
23160a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
23170c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
23180a708f8fSGustavo F. Padovan 
231973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
23200a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
23210a708f8fSGustavo F. Padovan 
23220a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
23230a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
23240a708f8fSGustavo F. Padovan 	}
23250a708f8fSGustavo F. Padovan 
23260a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
23270a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
23280a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
23290a708f8fSGustavo F. Padovan 
23300a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
23310a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
23320a708f8fSGustavo F. Padovan 		else {
23330c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2334c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
23350a708f8fSGustavo F. Padovan 		}
23360c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
23370a708f8fSGustavo F. Padovan 
233842dceae2SAndrei Emeltchenko 		if (remote_efs) {
233942dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
234042dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
234142dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
234242dceae2SAndrei Emeltchenko 
234342dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
234442dceae2SAndrei Emeltchenko 
234542dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
234642dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
234742dceae2SAndrei Emeltchenko 
234842dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
234942dceae2SAndrei Emeltchenko 							sizeof(efs),
235042dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
23510e8b207eSAndrei Emeltchenko 			} else {
23523e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
23530e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
23540e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
235542dceae2SAndrei Emeltchenko 			}
235642dceae2SAndrei Emeltchenko 		}
235742dceae2SAndrei Emeltchenko 
23580a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
23590a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
236047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2361c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
23620a708f8fSGustavo F. Padovan 			break;
23630a708f8fSGustavo F. Padovan 
23640a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
23656327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
23662c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
23676327eb98SAndrei Emeltchenko 			else
23686327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
23696327eb98SAndrei Emeltchenko 
23702c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
23710a708f8fSGustavo F. Padovan 
2372c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2373c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2374c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2375c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2376c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2377c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2378c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
23790a708f8fSGustavo F. Padovan 
23800a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
23810a708f8fSGustavo F. Padovan 				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
23820a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
23830a708f8fSGustavo F. Padovan 				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
23840a708f8fSGustavo F. Padovan 
2385c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
23860a708f8fSGustavo F. Padovan 
23870a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
23880a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
23890a708f8fSGustavo F. Padovan 
239042dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
239142dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
239242dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
239342dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
239442dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
239542dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
239642dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
239742dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
239842dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
239942dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
240042dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
240142dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
240242dceae2SAndrei Emeltchenko 			}
24030a708f8fSGustavo F. Padovan 			break;
24040a708f8fSGustavo F. Padovan 
24050a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2406c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2407c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2408c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2409c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2410c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2411c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2412c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
24130a708f8fSGustavo F. Padovan 
2414c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
24150a708f8fSGustavo F. Padovan 
24160a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
24170a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
24180a708f8fSGustavo F. Padovan 
24190a708f8fSGustavo F. Padovan 			break;
24200a708f8fSGustavo F. Padovan 
24210a708f8fSGustavo F. Padovan 		default:
24220a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
24230a708f8fSGustavo F. Padovan 
24240a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
24250c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
24260a708f8fSGustavo F. Padovan 		}
24270a708f8fSGustavo F. Padovan 
24280a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2429c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
24300a708f8fSGustavo F. Padovan 	}
2431fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
24320a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
24330a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
24340a708f8fSGustavo F. Padovan 
24350a708f8fSGustavo F. Padovan 	return ptr - data;
24360a708f8fSGustavo F. Padovan }
24370a708f8fSGustavo F. Padovan 
2438b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
24390a708f8fSGustavo F. Padovan {
24400a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
24410a708f8fSGustavo F. Padovan 	void *ptr = req->data;
24420a708f8fSGustavo F. Padovan 	int type, olen;
24430a708f8fSGustavo F. Padovan 	unsigned long val;
244436e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
244566af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
24460a708f8fSGustavo F. Padovan 
2447fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
24480a708f8fSGustavo F. Padovan 
24490a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
24500a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
24510a708f8fSGustavo F. Padovan 
24520a708f8fSGustavo F. Padovan 		switch (type) {
24530a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
24540a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
24550a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
24560c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
24570a708f8fSGustavo F. Padovan 			} else
24580c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
24590c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
24600a708f8fSGustavo F. Padovan 			break;
24610a708f8fSGustavo F. Padovan 
24620a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
24630c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
24640a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
24650c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
24660a708f8fSGustavo F. Padovan 			break;
24670a708f8fSGustavo F. Padovan 
24680a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
24690a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
24700a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
24710a708f8fSGustavo F. Padovan 
2472c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
24730c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
24740a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
24750a708f8fSGustavo F. Padovan 
247647d1ec61SGustavo F. Padovan 			chan->fcs = 0;
24770a708f8fSGustavo F. Padovan 
24780a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
24790a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
24800a708f8fSGustavo F. Padovan 			break;
24816327eb98SAndrei Emeltchenko 
24826327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
24836327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
24846327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
24853e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
24863e6b3b95SGustavo F. Padovan 							chan->tx_win);
24876327eb98SAndrei Emeltchenko 			break;
248866af7aafSAndrei Emeltchenko 
248966af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
249066af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
249166af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
249266af7aafSAndrei Emeltchenko 
249366af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
249466af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
249566af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
249666af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
249766af7aafSAndrei Emeltchenko 
249866af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
249966af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
250066af7aafSAndrei Emeltchenko 			break;
25010a708f8fSGustavo F. Padovan 		}
25020a708f8fSGustavo F. Padovan 	}
25030a708f8fSGustavo F. Padovan 
25040c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
25050a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
25060a708f8fSGustavo F. Padovan 
25070c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
25080a708f8fSGustavo F. Padovan 
25090e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
25100a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
25110a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
251247d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
251347d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
251447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
251566af7aafSAndrei Emeltchenko 
251666af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
251766af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
251866af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
251966af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
252066af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
252166af7aafSAndrei Emeltchenko 				chan->local_flush_to =
252266af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
252366af7aafSAndrei Emeltchenko 			}
25240a708f8fSGustavo F. Padovan 			break;
252566af7aafSAndrei Emeltchenko 
25260a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
252747d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
25280a708f8fSGustavo F. Padovan 		}
25290a708f8fSGustavo F. Padovan 	}
25300a708f8fSGustavo F. Padovan 
2531fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
25320a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
25330a708f8fSGustavo F. Padovan 
25340a708f8fSGustavo F. Padovan 	return ptr - data;
25350a708f8fSGustavo F. Padovan }
25360a708f8fSGustavo F. Padovan 
2537fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
25380a708f8fSGustavo F. Padovan {
25390a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
25400a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
25410a708f8fSGustavo F. Padovan 
2542fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
25430a708f8fSGustavo F. Padovan 
2544fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
25450a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
25460a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
25470a708f8fSGustavo F. Padovan 
25480a708f8fSGustavo F. Padovan 	return ptr - data;
25490a708f8fSGustavo F. Padovan }
25500a708f8fSGustavo F. Padovan 
25518c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
2552710f9b0aSGustavo F. Padovan {
2553710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
25548c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
2555710f9b0aSGustavo F. Padovan 	u8 buf[128];
2556710f9b0aSGustavo F. Padovan 
2557fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
2558fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
2559710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2560710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2561710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
2562710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2563710f9b0aSGustavo F. Padovan 
2564c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
2565710f9b0aSGustavo F. Padovan 		return;
2566710f9b0aSGustavo F. Padovan 
2567710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2568710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
2569710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
2570710f9b0aSGustavo F. Padovan }
2571710f9b0aSGustavo F. Padovan 
257247d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
25730a708f8fSGustavo F. Padovan {
25740a708f8fSGustavo F. Padovan 	int type, olen;
25750a708f8fSGustavo F. Padovan 	unsigned long val;
25760a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
25770a708f8fSGustavo F. Padovan 
257847d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
25790a708f8fSGustavo F. Padovan 
25800c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
25810a708f8fSGustavo F. Padovan 		return;
25820a708f8fSGustavo F. Padovan 
25830a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
25840a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
25850a708f8fSGustavo F. Padovan 
25860a708f8fSGustavo F. Padovan 		switch (type) {
25870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
25880a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
25890a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
25900a708f8fSGustavo F. Padovan 			goto done;
25910a708f8fSGustavo F. Padovan 		}
25920a708f8fSGustavo F. Padovan 	}
25930a708f8fSGustavo F. Padovan 
259436e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
259536e999a8SMat Martineau 	 * did not send an RFC option.
259636e999a8SMat Martineau 	 */
259736e999a8SMat Martineau 	rfc.mode = chan->mode;
259836e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
259936e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
260036e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
260136e999a8SMat Martineau 
260236e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
260336e999a8SMat Martineau 
26040a708f8fSGustavo F. Padovan done:
26050a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
26060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
260747d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
260847d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
260947d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
26100a708f8fSGustavo F. Padovan 		break;
26110a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
261247d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
26130a708f8fSGustavo F. Padovan 	}
26140a708f8fSGustavo F. Padovan }
26150a708f8fSGustavo F. Padovan 
26160a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
26170a708f8fSGustavo F. Padovan {
2618e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
26190a708f8fSGustavo F. Padovan 
2620e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
26210a708f8fSGustavo F. Padovan 		return 0;
26220a708f8fSGustavo F. Padovan 
26230a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
26240a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
262517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
26260a708f8fSGustavo F. Padovan 
26270a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
26280a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
26290a708f8fSGustavo F. Padovan 
26300a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
26310a708f8fSGustavo F. Padovan 	}
26320a708f8fSGustavo F. Padovan 
26330a708f8fSGustavo F. Padovan 	return 0;
26340a708f8fSGustavo F. Padovan }
26350a708f8fSGustavo F. Padovan 
26360a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
26370a708f8fSGustavo F. Padovan {
26380a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
26390a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
264023691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
26410a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
26420a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
26430a708f8fSGustavo F. Padovan 
26440a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
26450a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
26460a708f8fSGustavo F. Padovan 
2647097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
26480a708f8fSGustavo F. Padovan 
26490a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
265023691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
265123691d75SGustavo F. Padovan 	if (!pchan) {
26520a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
26530a708f8fSGustavo F. Padovan 		goto sendresp;
26540a708f8fSGustavo F. Padovan 	}
26550a708f8fSGustavo F. Padovan 
265623691d75SGustavo F. Padovan 	parent = pchan->sk;
265723691d75SGustavo F. Padovan 
26583df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2659aa2ac881SGustavo F. Padovan 	lock_sock(parent);
26600a708f8fSGustavo F. Padovan 
26610a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
26620a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
26630a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
26649f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
26650a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
26660a708f8fSGustavo F. Padovan 		goto response;
26670a708f8fSGustavo F. Padovan 	}
26680a708f8fSGustavo F. Padovan 
26690a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
26700a708f8fSGustavo F. Padovan 
26710a708f8fSGustavo F. Padovan 	/* Check for backlog size */
26720a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
26730a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
26740a708f8fSGustavo F. Padovan 		goto response;
26750a708f8fSGustavo F. Padovan 	}
26760a708f8fSGustavo F. Padovan 
267780808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
267880808e43SGustavo F. Padovan 	if (!chan)
26790a708f8fSGustavo F. Padovan 		goto response;
26800a708f8fSGustavo F. Padovan 
268180808e43SGustavo F. Padovan 	sk = chan->sk;
268280808e43SGustavo F. Padovan 
26830a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
2684baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
26850a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
2686ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
26870a708f8fSGustavo F. Padovan 		goto response;
26880a708f8fSGustavo F. Padovan 	}
26890a708f8fSGustavo F. Padovan 
26900a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
26910a708f8fSGustavo F. Padovan 
26920a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
26930a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
2694fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
2695fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
26960a708f8fSGustavo F. Padovan 
2697d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
2698d1010240SGustavo F. Padovan 
26996be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
270048454079SGustavo F. Padovan 
2701fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
27020a708f8fSGustavo F. Padovan 
2703c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
27040a708f8fSGustavo F. Padovan 
2705fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
27060a708f8fSGustavo F. Padovan 
27070a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
2708d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
27090a708f8fSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup) {
27100e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
27110a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
27120a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
27130a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
27140a708f8fSGustavo F. Padovan 			} else {
27150e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
27160a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
27170a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
27180a708f8fSGustavo F. Padovan 			}
27190a708f8fSGustavo F. Padovan 		} else {
27200e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
27210a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
27220a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
27230a708f8fSGustavo F. Padovan 		}
27240a708f8fSGustavo F. Padovan 	} else {
27250e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
27260a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
27270a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
27280a708f8fSGustavo F. Padovan 	}
27290a708f8fSGustavo F. Padovan 
27300a708f8fSGustavo F. Padovan response:
2731aa2ac881SGustavo F. Padovan 	release_sock(parent);
27323df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
27330a708f8fSGustavo F. Padovan 
27340a708f8fSGustavo F. Padovan sendresp:
27350a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
27360a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
27370a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
27380a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
27390a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
27400a708f8fSGustavo F. Padovan 
27410a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
27420a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
27430a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
27440a708f8fSGustavo F. Padovan 
27450a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
27460a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
27470a708f8fSGustavo F. Padovan 
2748ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
27490a708f8fSGustavo F. Padovan 
27500a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
27510a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
27520a708f8fSGustavo F. Padovan 	}
27530a708f8fSGustavo F. Padovan 
2754c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
27550a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
27560a708f8fSGustavo F. Padovan 		u8 buf[128];
2757c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
27580a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
275973ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
276073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
27610a708f8fSGustavo F. Padovan 	}
27620a708f8fSGustavo F. Padovan 
27630a708f8fSGustavo F. Padovan 	return 0;
27640a708f8fSGustavo F. Padovan }
27650a708f8fSGustavo F. Padovan 
27660a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
27670a708f8fSGustavo F. Padovan {
27680a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
27690a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
277048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
27710a708f8fSGustavo F. Padovan 	u8 req[128];
27723df91ea2SAndrei Emeltchenko 	int err;
27730a708f8fSGustavo F. Padovan 
27740a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
27750a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
27760a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
27770a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
27780a708f8fSGustavo F. Padovan 
27791b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
27801b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
27810a708f8fSGustavo F. Padovan 
27823df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
27833df91ea2SAndrei Emeltchenko 
27840a708f8fSGustavo F. Padovan 	if (scid) {
27853df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
27863df91ea2SAndrei Emeltchenko 		if (!chan) {
27873df91ea2SAndrei Emeltchenko 			err = -EFAULT;
27883df91ea2SAndrei Emeltchenko 			goto unlock;
27893df91ea2SAndrei Emeltchenko 		}
27900a708f8fSGustavo F. Padovan 	} else {
27913df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
27923df91ea2SAndrei Emeltchenko 		if (!chan) {
27933df91ea2SAndrei Emeltchenko 			err = -EFAULT;
27943df91ea2SAndrei Emeltchenko 			goto unlock;
27953df91ea2SAndrei Emeltchenko 		}
27960a708f8fSGustavo F. Padovan 	}
27970a708f8fSGustavo F. Padovan 
27983df91ea2SAndrei Emeltchenko 	err = 0;
27993df91ea2SAndrei Emeltchenko 
28006be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
280148454079SGustavo F. Padovan 
28020a708f8fSGustavo F. Padovan 	switch (result) {
28030a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
280489bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
2805fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
2806fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
2807c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
28080a708f8fSGustavo F. Padovan 
2809c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
28100a708f8fSGustavo F. Padovan 			break;
28110a708f8fSGustavo F. Padovan 
28120a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
281373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
281473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
28150a708f8fSGustavo F. Padovan 		break;
28160a708f8fSGustavo F. Padovan 
28170a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
2818c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
28190a708f8fSGustavo F. Padovan 		break;
28200a708f8fSGustavo F. Padovan 
28210a708f8fSGustavo F. Padovan 	default:
282248454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
28230a708f8fSGustavo F. Padovan 		break;
28240a708f8fSGustavo F. Padovan 	}
28250a708f8fSGustavo F. Padovan 
28266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
28273df91ea2SAndrei Emeltchenko 
28283df91ea2SAndrei Emeltchenko unlock:
28293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
28303df91ea2SAndrei Emeltchenko 
28313df91ea2SAndrei Emeltchenko 	return err;
28320a708f8fSGustavo F. Padovan }
28330a708f8fSGustavo F. Padovan 
283447d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
28350a708f8fSGustavo F. Padovan {
28360a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
28370a708f8fSGustavo F. Padovan 	 * sides request it.
28380a708f8fSGustavo F. Padovan 	 */
28390c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
284047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
2841c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
284247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
28430a708f8fSGustavo F. Padovan }
28440a708f8fSGustavo F. Padovan 
28450a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
28460a708f8fSGustavo F. Padovan {
28470a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
28480a708f8fSGustavo F. Padovan 	u16 dcid, flags;
28490a708f8fSGustavo F. Padovan 	u8 rsp[64];
285048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
28510a708f8fSGustavo F. Padovan 	int len;
28520a708f8fSGustavo F. Padovan 
28530a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
28540a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
28550a708f8fSGustavo F. Padovan 
28560a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
28570a708f8fSGustavo F. Padovan 
2858baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
285948454079SGustavo F. Padovan 	if (!chan)
28600a708f8fSGustavo F. Padovan 		return -ENOENT;
28610a708f8fSGustavo F. Padovan 
28626be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
286348454079SGustavo F. Padovan 
2864033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
2865e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
28660a708f8fSGustavo F. Padovan 
2867e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
2868e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
2869e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
2870e2fd318eSIlia Kolomisnky 
28710a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
28720a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
28730a708f8fSGustavo F. Padovan 		goto unlock;
28740a708f8fSGustavo F. Padovan 	}
28750a708f8fSGustavo F. Padovan 
28760a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
28770a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
28787ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
28790a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2880fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
28810a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
28820a708f8fSGustavo F. Padovan 		goto unlock;
28830a708f8fSGustavo F. Padovan 	}
28840a708f8fSGustavo F. Padovan 
28850a708f8fSGustavo F. Padovan 	/* Store config. */
288673ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
288773ffa904SGustavo F. Padovan 	chan->conf_len += len;
28880a708f8fSGustavo F. Padovan 
28890a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
28900a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
28910a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
2892fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
28930a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
28940a708f8fSGustavo F. Padovan 		goto unlock;
28950a708f8fSGustavo F. Padovan 	}
28960a708f8fSGustavo F. Padovan 
28970a708f8fSGustavo F. Padovan 	/* Complete config. */
289873ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
28990a708f8fSGustavo F. Padovan 	if (len < 0) {
2900e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
29010a708f8fSGustavo F. Padovan 		goto unlock;
29020a708f8fSGustavo F. Padovan 	}
29030a708f8fSGustavo F. Padovan 
29040a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
290573ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
29060a708f8fSGustavo F. Padovan 
29070a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
290873ffa904SGustavo F. Padovan 	chan->conf_len = 0;
29090a708f8fSGustavo F. Padovan 
2910c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
29110a708f8fSGustavo F. Padovan 		goto unlock;
29120a708f8fSGustavo F. Padovan 
2913c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
291447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
29150a708f8fSGustavo F. Padovan 
291689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
29170a708f8fSGustavo F. Padovan 
291842e5c802SGustavo F. Padovan 		chan->next_tx_seq = 0;
291942e5c802SGustavo F. Padovan 		chan->expected_tx_seq = 0;
292058d35f87SGustavo F. Padovan 		skb_queue_head_init(&chan->tx_q);
29210c1bc5c6SGustavo F. Padovan 		if (chan->mode == L2CAP_MODE_ERTM)
2922525cd185SGustavo F. Padovan 			l2cap_ertm_init(chan);
29230a708f8fSGustavo F. Padovan 
2924cf4cd009SAndrei Emeltchenko 		l2cap_chan_ready(chan);
29250a708f8fSGustavo F. Padovan 		goto unlock;
29260a708f8fSGustavo F. Padovan 	}
29270a708f8fSGustavo F. Padovan 
2928c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
29290a708f8fSGustavo F. Padovan 		u8 buf[64];
29300a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
293173ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
293273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
29330a708f8fSGustavo F. Padovan 	}
29340a708f8fSGustavo F. Padovan 
29350e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
29360e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
29370e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
29380e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
29390e8b207eSAndrei Emeltchenko 
29400e8b207eSAndrei Emeltchenko 		/* check compatibility */
29410e8b207eSAndrei Emeltchenko 
29420e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
29430e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
29440e8b207eSAndrei Emeltchenko 
29450e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
29460e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
29470e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
29480e8b207eSAndrei Emeltchenko 	}
29490e8b207eSAndrei Emeltchenko 
29500a708f8fSGustavo F. Padovan unlock:
29516be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
29520a708f8fSGustavo F. Padovan 	return 0;
29530a708f8fSGustavo F. Padovan }
29540a708f8fSGustavo F. Padovan 
29550a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29560a708f8fSGustavo F. Padovan {
29570a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
29580a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
295948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
296061386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
29610a708f8fSGustavo F. Padovan 
29620a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
29630a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
29640a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
29650a708f8fSGustavo F. Padovan 
296661386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
296761386cbaSAndrei Emeltchenko 	       result, len);
29680a708f8fSGustavo F. Padovan 
2969baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
297048454079SGustavo F. Padovan 	if (!chan)
29710a708f8fSGustavo F. Padovan 		return 0;
29720a708f8fSGustavo F. Padovan 
29736be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
297448454079SGustavo F. Padovan 
29750a708f8fSGustavo F. Padovan 	switch (result) {
29760a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
297747d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
29780e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
29790a708f8fSGustavo F. Padovan 		break;
29800a708f8fSGustavo F. Padovan 
29810e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
29820e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
29830e8b207eSAndrei Emeltchenko 
29840e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
29850e8b207eSAndrei Emeltchenko 			char buf[64];
29860e8b207eSAndrei Emeltchenko 
29870e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
29880e8b207eSAndrei Emeltchenko 								buf, &result);
29890e8b207eSAndrei Emeltchenko 			if (len < 0) {
29900e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
29910e8b207eSAndrei Emeltchenko 				goto done;
29920e8b207eSAndrei Emeltchenko 			}
29930e8b207eSAndrei Emeltchenko 
29940e8b207eSAndrei Emeltchenko 			/* check compatibility */
29950e8b207eSAndrei Emeltchenko 
29960e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
29970e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
29980e8b207eSAndrei Emeltchenko 
29990e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
30000e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
30010e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
30020e8b207eSAndrei Emeltchenko 		}
30030e8b207eSAndrei Emeltchenko 		goto done;
30040e8b207eSAndrei Emeltchenko 
30050a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
300673ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
30070a708f8fSGustavo F. Padovan 			char req[64];
30080a708f8fSGustavo F. Padovan 
30090a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3010e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
30110a708f8fSGustavo F. Padovan 				goto done;
30120a708f8fSGustavo F. Padovan 			}
30130a708f8fSGustavo F. Padovan 
30140a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
30150a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3016b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3017b4450035SGustavo F. Padovan 								req, &result);
30180a708f8fSGustavo F. Padovan 			if (len < 0) {
3019e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
30200a708f8fSGustavo F. Padovan 				goto done;
30210a708f8fSGustavo F. Padovan 			}
30220a708f8fSGustavo F. Padovan 
30230a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
30240a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
302573ffa904SGustavo F. Padovan 			chan->num_conf_req++;
30260a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
30270a708f8fSGustavo F. Padovan 				goto done;
30280a708f8fSGustavo F. Padovan 			break;
30290a708f8fSGustavo F. Padovan 		}
30300a708f8fSGustavo F. Padovan 
30310a708f8fSGustavo F. Padovan 	default:
30326be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
30332e0052e4SAndrei Emeltchenko 
3034ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3035e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
30360a708f8fSGustavo F. Padovan 		goto done;
30370a708f8fSGustavo F. Padovan 	}
30380a708f8fSGustavo F. Padovan 
30390a708f8fSGustavo F. Padovan 	if (flags & 0x01)
30400a708f8fSGustavo F. Padovan 		goto done;
30410a708f8fSGustavo F. Padovan 
3042c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
30430a708f8fSGustavo F. Padovan 
3044c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
304547d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
30460a708f8fSGustavo F. Padovan 
304789bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
304842e5c802SGustavo F. Padovan 		chan->next_tx_seq = 0;
304942e5c802SGustavo F. Padovan 		chan->expected_tx_seq = 0;
305058d35f87SGustavo F. Padovan 		skb_queue_head_init(&chan->tx_q);
30510c1bc5c6SGustavo F. Padovan 		if (chan->mode ==  L2CAP_MODE_ERTM)
3052525cd185SGustavo F. Padovan 			l2cap_ertm_init(chan);
30530a708f8fSGustavo F. Padovan 
3054cf4cd009SAndrei Emeltchenko 		l2cap_chan_ready(chan);
30550a708f8fSGustavo F. Padovan 	}
30560a708f8fSGustavo F. Padovan 
30570a708f8fSGustavo F. Padovan done:
30586be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
30590a708f8fSGustavo F. Padovan 	return 0;
30600a708f8fSGustavo F. Padovan }
30610a708f8fSGustavo F. Padovan 
30620a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
30630a708f8fSGustavo F. Padovan {
30640a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
30650a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
30660a708f8fSGustavo F. Padovan 	u16 dcid, scid;
306748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30680a708f8fSGustavo F. Padovan 	struct sock *sk;
30690a708f8fSGustavo F. Padovan 
30700a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
30710a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
30720a708f8fSGustavo F. Padovan 
30730a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
30740a708f8fSGustavo F. Padovan 
30753df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30763df91ea2SAndrei Emeltchenko 
30773df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
30783df91ea2SAndrei Emeltchenko 	if (!chan) {
30793df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
30800a708f8fSGustavo F. Padovan 		return 0;
30813df91ea2SAndrei Emeltchenko 	}
30820a708f8fSGustavo F. Padovan 
30836be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
30846be36555SAndrei Emeltchenko 
308548454079SGustavo F. Padovan 	sk = chan->sk;
308648454079SGustavo F. Padovan 
3087fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3088fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
30890a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
30900a708f8fSGustavo F. Padovan 
30916be36555SAndrei Emeltchenko 	lock_sock(sk);
30920a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
30936be36555SAndrei Emeltchenko 	release_sock(sk);
30940a708f8fSGustavo F. Padovan 
309548454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
30966be36555SAndrei Emeltchenko 
30976be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
30980a708f8fSGustavo F. Padovan 
3099ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
31003df91ea2SAndrei Emeltchenko 
31013df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
31023df91ea2SAndrei Emeltchenko 
31030a708f8fSGustavo F. Padovan 	return 0;
31040a708f8fSGustavo F. Padovan }
31050a708f8fSGustavo F. Padovan 
31060a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31070a708f8fSGustavo F. Padovan {
31080a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
31090a708f8fSGustavo F. Padovan 	u16 dcid, scid;
311048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
31110a708f8fSGustavo F. Padovan 
31120a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
31130a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
31140a708f8fSGustavo F. Padovan 
31150a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
31160a708f8fSGustavo F. Padovan 
31173df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
31183df91ea2SAndrei Emeltchenko 
31193df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
31203df91ea2SAndrei Emeltchenko 	if (!chan) {
31213df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
31220a708f8fSGustavo F. Padovan 		return 0;
31233df91ea2SAndrei Emeltchenko 	}
31240a708f8fSGustavo F. Padovan 
31256be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
312648454079SGustavo F. Padovan 
312748454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
31286be36555SAndrei Emeltchenko 
31296be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
31300a708f8fSGustavo F. Padovan 
3131ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
31323df91ea2SAndrei Emeltchenko 
31333df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
31343df91ea2SAndrei Emeltchenko 
31350a708f8fSGustavo F. Padovan 	return 0;
31360a708f8fSGustavo F. Padovan }
31370a708f8fSGustavo F. Padovan 
31380a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31390a708f8fSGustavo F. Padovan {
31400a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
31410a708f8fSGustavo F. Padovan 	u16 type;
31420a708f8fSGustavo F. Padovan 
31430a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
31440a708f8fSGustavo F. Padovan 
31450a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
31460a708f8fSGustavo F. Padovan 
31470a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
31480a708f8fSGustavo F. Padovan 		u8 buf[8];
31490a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
31500a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
31510a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
31520a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
31530a708f8fSGustavo F. Padovan 		if (!disable_ertm)
31540a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
31550a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3156a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
31576327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
31586327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3159a5fd6f30SAndrei Emeltchenko 
31600a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
31610a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
31620a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
31630a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
31640a708f8fSGustavo F. Padovan 		u8 buf[12];
31650a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
316650a147cdSMat Martineau 
316750a147cdSMat Martineau 		if (enable_hs)
316850a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
316950a147cdSMat Martineau 		else
317050a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
317150a147cdSMat Martineau 
31720a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
31730a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3174c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
31750a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
31760a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
31770a708f8fSGustavo F. Padovan 	} else {
31780a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
31790a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
31800a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
31810a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
31820a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
31830a708f8fSGustavo F. Padovan 	}
31840a708f8fSGustavo F. Padovan 
31850a708f8fSGustavo F. Padovan 	return 0;
31860a708f8fSGustavo F. Padovan }
31870a708f8fSGustavo F. Padovan 
31880a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
31890a708f8fSGustavo F. Padovan {
31900a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
31910a708f8fSGustavo F. Padovan 	u16 type, result;
31920a708f8fSGustavo F. Padovan 
31930a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
31940a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
31950a708f8fSGustavo F. Padovan 
31960a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
31970a708f8fSGustavo F. Padovan 
3198e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3199e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3200e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3201e90165beSAndrei Emeltchenko 		return 0;
3202e90165beSAndrei Emeltchenko 
320317cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
32040a708f8fSGustavo F. Padovan 
32050a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
32060a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
32070a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
32080a708f8fSGustavo F. Padovan 
32090a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
32100a708f8fSGustavo F. Padovan 
32110a708f8fSGustavo F. Padovan 		return 0;
32120a708f8fSGustavo F. Padovan 	}
32130a708f8fSGustavo F. Padovan 
3214978c93b9SAndrei Emeltchenko 	switch (type) {
3215978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
32160a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
32170a708f8fSGustavo F. Padovan 
32180a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
32190a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
32200a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
32210a708f8fSGustavo F. Padovan 
32220a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
32230a708f8fSGustavo F. Padovan 
32240a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
32250a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
32260a708f8fSGustavo F. Padovan 		} else {
32270a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
32280a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
32290a708f8fSGustavo F. Padovan 
32300a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
32310a708f8fSGustavo F. Padovan 		}
3232978c93b9SAndrei Emeltchenko 		break;
3233978c93b9SAndrei Emeltchenko 
3234978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3235978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
32360a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
32370a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
32380a708f8fSGustavo F. Padovan 
32390a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3240978c93b9SAndrei Emeltchenko 		break;
32410a708f8fSGustavo F. Padovan 	}
32420a708f8fSGustavo F. Padovan 
32430a708f8fSGustavo F. Padovan 	return 0;
32440a708f8fSGustavo F. Padovan }
32450a708f8fSGustavo F. Padovan 
3246f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3247f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3248f94ff6ffSMat Martineau 					void *data)
3249f94ff6ffSMat Martineau {
3250f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3251f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3252f94ff6ffSMat Martineau 	u16 psm, scid;
3253f94ff6ffSMat Martineau 
3254f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3255f94ff6ffSMat Martineau 		return -EPROTO;
3256f94ff6ffSMat Martineau 
3257f94ff6ffSMat Martineau 	if (!enable_hs)
3258f94ff6ffSMat Martineau 		return -EINVAL;
3259f94ff6ffSMat Martineau 
3260f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3261f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3262f94ff6ffSMat Martineau 
3263f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3264f94ff6ffSMat Martineau 
3265f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3266f94ff6ffSMat Martineau 	rsp.dcid = 0;
3267f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
3268f94ff6ffSMat Martineau 	rsp.result = L2CAP_CR_NO_MEM;
3269f94ff6ffSMat Martineau 	rsp.status = L2CAP_CS_NO_INFO;
3270f94ff6ffSMat Martineau 
3271f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3272f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3273f94ff6ffSMat Martineau 
3274f94ff6ffSMat Martineau 	return 0;
3275f94ff6ffSMat Martineau }
3276f94ff6ffSMat Martineau 
3277f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3278f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3279f94ff6ffSMat Martineau {
3280f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3281f94ff6ffSMat Martineau 
3282f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3283f94ff6ffSMat Martineau }
3284f94ff6ffSMat Martineau 
32858d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
32868d5a04a1SMat Martineau 							u16 icid, u16 result)
32878d5a04a1SMat Martineau {
32888d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
32898d5a04a1SMat Martineau 
32908d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
32918d5a04a1SMat Martineau 
32928d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
32938d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
32948d5a04a1SMat Martineau 
32958d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
32968d5a04a1SMat Martineau }
32978d5a04a1SMat Martineau 
32988d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
32998d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
33008d5a04a1SMat Martineau {
33018d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
33028d5a04a1SMat Martineau 	u8 ident;
33038d5a04a1SMat Martineau 
33048d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
33058d5a04a1SMat Martineau 
33068d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
33078d5a04a1SMat Martineau 	if (chan)
33088d5a04a1SMat Martineau 		chan->ident = ident;
33098d5a04a1SMat Martineau 
33108d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
33118d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
33128d5a04a1SMat Martineau 
33138d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
33148d5a04a1SMat Martineau }
33158d5a04a1SMat Martineau 
33168d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
33178d5a04a1SMat Martineau 								u16 icid)
33188d5a04a1SMat Martineau {
33198d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
33208d5a04a1SMat Martineau 
33218d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
33228d5a04a1SMat Martineau 
33238d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
33248d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
33258d5a04a1SMat Martineau }
33268d5a04a1SMat Martineau 
33278d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
33288d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
33298d5a04a1SMat Martineau {
33308d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
33318d5a04a1SMat Martineau 	u16 icid = 0;
33328d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
33338d5a04a1SMat Martineau 
33348d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
33358d5a04a1SMat Martineau 		return -EPROTO;
33368d5a04a1SMat Martineau 
33378d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
33388d5a04a1SMat Martineau 
33398d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
33408d5a04a1SMat Martineau 
33418d5a04a1SMat Martineau 	if (!enable_hs)
33428d5a04a1SMat Martineau 		return -EINVAL;
33438d5a04a1SMat Martineau 
33448d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
33458d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
33468d5a04a1SMat Martineau 
33478d5a04a1SMat Martineau 	return 0;
33488d5a04a1SMat Martineau }
33498d5a04a1SMat Martineau 
33508d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
33518d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
33528d5a04a1SMat Martineau {
33538d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
33548d5a04a1SMat Martineau 	u16 icid, result;
33558d5a04a1SMat Martineau 
33568d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
33578d5a04a1SMat Martineau 		return -EPROTO;
33588d5a04a1SMat Martineau 
33598d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
33608d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
33618d5a04a1SMat Martineau 
33628d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
33638d5a04a1SMat Martineau 
33648d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
33658d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
33668d5a04a1SMat Martineau 
33678d5a04a1SMat Martineau 	return 0;
33688d5a04a1SMat Martineau }
33698d5a04a1SMat Martineau 
33708d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
33718d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
33728d5a04a1SMat Martineau {
33738d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
33748d5a04a1SMat Martineau 	u16 icid, result;
33758d5a04a1SMat Martineau 
33768d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
33778d5a04a1SMat Martineau 		return -EPROTO;
33788d5a04a1SMat Martineau 
33798d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
33808d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
33818d5a04a1SMat Martineau 
33828d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
33838d5a04a1SMat Martineau 
33848d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
33858d5a04a1SMat Martineau 
33868d5a04a1SMat Martineau 	return 0;
33878d5a04a1SMat Martineau }
33888d5a04a1SMat Martineau 
33898d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
33908d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
33918d5a04a1SMat Martineau {
33928d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
33938d5a04a1SMat Martineau 	u16 icid;
33948d5a04a1SMat Martineau 
33958d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
33968d5a04a1SMat Martineau 		return -EPROTO;
33978d5a04a1SMat Martineau 
33988d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
33998d5a04a1SMat Martineau 
34008d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
34018d5a04a1SMat Martineau 
34028d5a04a1SMat Martineau 	return 0;
34038d5a04a1SMat Martineau }
34048d5a04a1SMat Martineau 
3405e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3406de73115aSClaudio Takahasi 							u16 to_multiplier)
3407de73115aSClaudio Takahasi {
3408de73115aSClaudio Takahasi 	u16 max_latency;
3409de73115aSClaudio Takahasi 
3410de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3411de73115aSClaudio Takahasi 		return -EINVAL;
3412de73115aSClaudio Takahasi 
3413de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3414de73115aSClaudio Takahasi 		return -EINVAL;
3415de73115aSClaudio Takahasi 
3416de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3417de73115aSClaudio Takahasi 		return -EINVAL;
3418de73115aSClaudio Takahasi 
3419de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3420de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3421de73115aSClaudio Takahasi 		return -EINVAL;
3422de73115aSClaudio Takahasi 
3423de73115aSClaudio Takahasi 	return 0;
3424de73115aSClaudio Takahasi }
3425de73115aSClaudio Takahasi 
3426de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3427de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3428de73115aSClaudio Takahasi {
3429de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3430de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3431de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3432de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
34332ce603ebSClaudio Takahasi 	int err;
3434de73115aSClaudio Takahasi 
3435de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3436de73115aSClaudio Takahasi 		return -EINVAL;
3437de73115aSClaudio Takahasi 
3438de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3439de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3440de73115aSClaudio Takahasi 		return -EPROTO;
3441de73115aSClaudio Takahasi 
3442de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
3443de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
3444de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
3445de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
3446de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
3447de73115aSClaudio Takahasi 
3448de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3449de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
3450de73115aSClaudio Takahasi 
3451de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
34522ce603ebSClaudio Takahasi 
34532ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
34542ce603ebSClaudio Takahasi 	if (err)
3455de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3456de73115aSClaudio Takahasi 	else
3457de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3458de73115aSClaudio Takahasi 
3459de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3460de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
3461de73115aSClaudio Takahasi 
34622ce603ebSClaudio Takahasi 	if (!err)
34632ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
34642ce603ebSClaudio Takahasi 
3465de73115aSClaudio Takahasi 	return 0;
3466de73115aSClaudio Takahasi }
3467de73115aSClaudio Takahasi 
34683300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
34693300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
34703300d9a9SClaudio Takahasi {
34713300d9a9SClaudio Takahasi 	int err = 0;
34723300d9a9SClaudio Takahasi 
34733300d9a9SClaudio Takahasi 	switch (cmd->code) {
34743300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
34753300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
34763300d9a9SClaudio Takahasi 		break;
34773300d9a9SClaudio Takahasi 
34783300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
34793300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
34803300d9a9SClaudio Takahasi 		break;
34813300d9a9SClaudio Takahasi 
34823300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
34833300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
34843300d9a9SClaudio Takahasi 		break;
34853300d9a9SClaudio Takahasi 
34863300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
34873300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
34883300d9a9SClaudio Takahasi 		break;
34893300d9a9SClaudio Takahasi 
34903300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
34913300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
34923300d9a9SClaudio Takahasi 		break;
34933300d9a9SClaudio Takahasi 
34943300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
34953300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
34963300d9a9SClaudio Takahasi 		break;
34973300d9a9SClaudio Takahasi 
34983300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
34993300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
35003300d9a9SClaudio Takahasi 		break;
35013300d9a9SClaudio Takahasi 
35023300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
35033300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
35043300d9a9SClaudio Takahasi 		break;
35053300d9a9SClaudio Takahasi 
35063300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
35073300d9a9SClaudio Takahasi 		break;
35083300d9a9SClaudio Takahasi 
35093300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
35103300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
35113300d9a9SClaudio Takahasi 		break;
35123300d9a9SClaudio Takahasi 
35133300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
35143300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
35153300d9a9SClaudio Takahasi 		break;
35163300d9a9SClaudio Takahasi 
3517f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
3518f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3519f94ff6ffSMat Martineau 		break;
3520f94ff6ffSMat Martineau 
3521f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
3522f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
3523f94ff6ffSMat Martineau 		break;
3524f94ff6ffSMat Martineau 
35258d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
35268d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
35278d5a04a1SMat Martineau 		break;
35288d5a04a1SMat Martineau 
35298d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
35308d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
35318d5a04a1SMat Martineau 		break;
35328d5a04a1SMat Martineau 
35338d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
35348d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
35358d5a04a1SMat Martineau 		break;
35368d5a04a1SMat Martineau 
35378d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
35388d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
35398d5a04a1SMat Martineau 		break;
35408d5a04a1SMat Martineau 
35413300d9a9SClaudio Takahasi 	default:
35423300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
35433300d9a9SClaudio Takahasi 		err = -EINVAL;
35443300d9a9SClaudio Takahasi 		break;
35453300d9a9SClaudio Takahasi 	}
35463300d9a9SClaudio Takahasi 
35473300d9a9SClaudio Takahasi 	return err;
35483300d9a9SClaudio Takahasi }
35493300d9a9SClaudio Takahasi 
35503300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
35513300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
35523300d9a9SClaudio Takahasi {
35533300d9a9SClaudio Takahasi 	switch (cmd->code) {
35543300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
35553300d9a9SClaudio Takahasi 		return 0;
35563300d9a9SClaudio Takahasi 
35573300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
3558de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
35593300d9a9SClaudio Takahasi 
35603300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
35613300d9a9SClaudio Takahasi 		return 0;
35623300d9a9SClaudio Takahasi 
35633300d9a9SClaudio Takahasi 	default:
35643300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
35653300d9a9SClaudio Takahasi 		return -EINVAL;
35663300d9a9SClaudio Takahasi 	}
35673300d9a9SClaudio Takahasi }
35683300d9a9SClaudio Takahasi 
35693300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
35703300d9a9SClaudio Takahasi 							struct sk_buff *skb)
35710a708f8fSGustavo F. Padovan {
35720a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
35730a708f8fSGustavo F. Padovan 	int len = skb->len;
35740a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
35753300d9a9SClaudio Takahasi 	int err;
35760a708f8fSGustavo F. Padovan 
35770a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
35780a708f8fSGustavo F. Padovan 
35790a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
35800a708f8fSGustavo F. Padovan 		u16 cmd_len;
35810a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
35820a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
35830a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
35840a708f8fSGustavo F. Padovan 
35850a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
35860a708f8fSGustavo F. Padovan 
35870a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
35880a708f8fSGustavo F. Padovan 
35890a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
35900a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
35910a708f8fSGustavo F. Padovan 			break;
35920a708f8fSGustavo F. Padovan 		}
35930a708f8fSGustavo F. Padovan 
35943300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
35953300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
35963300d9a9SClaudio Takahasi 		else
35973300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
35980a708f8fSGustavo F. Padovan 
35990a708f8fSGustavo F. Padovan 		if (err) {
3600e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
36012c6d1a2eSGustavo F. Padovan 
36022c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
36030a708f8fSGustavo F. Padovan 
36040a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
3605e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
36060a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
36070a708f8fSGustavo F. Padovan 		}
36080a708f8fSGustavo F. Padovan 
36090a708f8fSGustavo F. Padovan 		data += cmd_len;
36100a708f8fSGustavo F. Padovan 		len  -= cmd_len;
36110a708f8fSGustavo F. Padovan 	}
36120a708f8fSGustavo F. Padovan 
36130a708f8fSGustavo F. Padovan 	kfree_skb(skb);
36140a708f8fSGustavo F. Padovan }
36150a708f8fSGustavo F. Padovan 
361647d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
36170a708f8fSGustavo F. Padovan {
36180a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
3619e4ca6d98SAndrei Emeltchenko 	int hdr_size;
3620e4ca6d98SAndrei Emeltchenko 
3621e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3622e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
3623e4ca6d98SAndrei Emeltchenko 	else
3624e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
36250a708f8fSGustavo F. Padovan 
362647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
362703a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
36280a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
36290a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
36300a708f8fSGustavo F. Padovan 
36310a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
36320a708f8fSGustavo F. Padovan 			return -EBADMSG;
36330a708f8fSGustavo F. Padovan 	}
36340a708f8fSGustavo F. Padovan 	return 0;
36350a708f8fSGustavo F. Padovan }
36360a708f8fSGustavo F. Padovan 
3637525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
36380a708f8fSGustavo F. Padovan {
363988843ab0SAndrei Emeltchenko 	u32 control = 0;
36400a708f8fSGustavo F. Padovan 
36416a026610SGustavo F. Padovan 	chan->frames_sent = 0;
36420a708f8fSGustavo F. Padovan 
36430b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
36440a708f8fSGustavo F. Padovan 
3645e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3646ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
3647525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
3648e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
36490a708f8fSGustavo F. Padovan 	}
36500a708f8fSGustavo F. Padovan 
3651e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
3652525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
36530a708f8fSGustavo F. Padovan 
3654525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
36550a708f8fSGustavo F. Padovan 
3656e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
36576a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
3658ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3659525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
36600a708f8fSGustavo F. Padovan 	}
36610a708f8fSGustavo F. Padovan }
36620a708f8fSGustavo F. Padovan 
3663fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
36640a708f8fSGustavo F. Padovan {
36650a708f8fSGustavo F. Padovan 	struct sk_buff *next_skb;
36660a708f8fSGustavo F. Padovan 	int tx_seq_offset, next_tx_seq_offset;
36670a708f8fSGustavo F. Padovan 
36680a708f8fSGustavo F. Padovan 	bt_cb(skb)->tx_seq = tx_seq;
36690a708f8fSGustavo F. Padovan 	bt_cb(skb)->sar = sar;
36700a708f8fSGustavo F. Padovan 
3671f1c6775bSGustavo F. Padovan 	next_skb = skb_peek(&chan->srej_q);
36720a708f8fSGustavo F. Padovan 
3673836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
36740a708f8fSGustavo F. Padovan 
3675039d9572SSzymon Janc 	while (next_skb) {
36760a708f8fSGustavo F. Padovan 		if (bt_cb(next_skb)->tx_seq == tx_seq)
36770a708f8fSGustavo F. Padovan 			return -EINVAL;
36780a708f8fSGustavo F. Padovan 
3679836be934SAndrei Emeltchenko 		next_tx_seq_offset = __seq_offset(chan,
3680836be934SAndrei Emeltchenko 				bt_cb(next_skb)->tx_seq, chan->buffer_seq);
36810a708f8fSGustavo F. Padovan 
36820a708f8fSGustavo F. Padovan 		if (next_tx_seq_offset > tx_seq_offset) {
3683f1c6775bSGustavo F. Padovan 			__skb_queue_before(&chan->srej_q, next_skb, skb);
36840a708f8fSGustavo F. Padovan 			return 0;
36850a708f8fSGustavo F. Padovan 		}
36860a708f8fSGustavo F. Padovan 
3687f1c6775bSGustavo F. Padovan 		if (skb_queue_is_last(&chan->srej_q, next_skb))
3688039d9572SSzymon Janc 			next_skb = NULL;
3689039d9572SSzymon Janc 		else
3690039d9572SSzymon Janc 			next_skb = skb_queue_next(&chan->srej_q, next_skb);
3691039d9572SSzymon Janc 	}
36920a708f8fSGustavo F. Padovan 
3693f1c6775bSGustavo F. Padovan 	__skb_queue_tail(&chan->srej_q, skb);
36940a708f8fSGustavo F. Padovan 
36950a708f8fSGustavo F. Padovan 	return 0;
36960a708f8fSGustavo F. Padovan }
36970a708f8fSGustavo F. Padovan 
369884084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
369984084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
37000a708f8fSGustavo F. Padovan {
370184084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
370284084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
370384084a31SMat Martineau 	 */
370484084a31SMat Martineau 	if (!skb_has_frag_list(skb))
370584084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
370684084a31SMat Martineau 
370784084a31SMat Martineau 	new_frag->next = NULL;
370884084a31SMat Martineau 
370984084a31SMat Martineau 	(*last_frag)->next = new_frag;
371084084a31SMat Martineau 	*last_frag = new_frag;
371184084a31SMat Martineau 
371284084a31SMat Martineau 	skb->len += new_frag->len;
371384084a31SMat Martineau 	skb->data_len += new_frag->len;
371484084a31SMat Martineau 	skb->truesize += new_frag->truesize;
371584084a31SMat Martineau }
371684084a31SMat Martineau 
371788843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
371884084a31SMat Martineau {
371984084a31SMat Martineau 	int err = -EINVAL;
37200a708f8fSGustavo F. Padovan 
37217e0ef6eeSAndrei Emeltchenko 	switch (__get_ctrl_sar(chan, control)) {
37227e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
372384084a31SMat Martineau 		if (chan->sdu)
372484084a31SMat Martineau 			break;
37250a708f8fSGustavo F. Padovan 
372684084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
372784084a31SMat Martineau 		break;
37280a708f8fSGustavo F. Padovan 
37297e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
373084084a31SMat Martineau 		if (chan->sdu)
373184084a31SMat Martineau 			break;
37320a708f8fSGustavo F. Padovan 
37336f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
373403a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
37350a708f8fSGustavo F. Padovan 
373684084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
373784084a31SMat Martineau 			err = -EMSGSIZE;
373884084a31SMat Martineau 			break;
373984084a31SMat Martineau 		}
37400a708f8fSGustavo F. Padovan 
374184084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
374284084a31SMat Martineau 			break;
374384084a31SMat Martineau 
374484084a31SMat Martineau 		chan->sdu = skb;
374584084a31SMat Martineau 		chan->sdu_last_frag = skb;
374684084a31SMat Martineau 
374784084a31SMat Martineau 		skb = NULL;
374884084a31SMat Martineau 		err = 0;
37490a708f8fSGustavo F. Padovan 		break;
37500a708f8fSGustavo F. Padovan 
37517e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
37526f61fd47SGustavo F. Padovan 		if (!chan->sdu)
375384084a31SMat Martineau 			break;
37540a708f8fSGustavo F. Padovan 
375584084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
375684084a31SMat Martineau 				&chan->sdu_last_frag);
375784084a31SMat Martineau 		skb = NULL;
37580a708f8fSGustavo F. Padovan 
375984084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
376084084a31SMat Martineau 			break;
37610a708f8fSGustavo F. Padovan 
376284084a31SMat Martineau 		err = 0;
37630a708f8fSGustavo F. Padovan 		break;
37640a708f8fSGustavo F. Padovan 
37657e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
37666f61fd47SGustavo F. Padovan 		if (!chan->sdu)
376784084a31SMat Martineau 			break;
37680a708f8fSGustavo F. Padovan 
376984084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
377084084a31SMat Martineau 				&chan->sdu_last_frag);
377184084a31SMat Martineau 		skb = NULL;
37720a708f8fSGustavo F. Padovan 
377384084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
377484084a31SMat Martineau 			break;
37750a708f8fSGustavo F. Padovan 
377684084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
37770a708f8fSGustavo F. Padovan 
377884084a31SMat Martineau 		if (!err) {
377984084a31SMat Martineau 			/* Reassembly complete */
378084084a31SMat Martineau 			chan->sdu = NULL;
378184084a31SMat Martineau 			chan->sdu_last_frag = NULL;
378284084a31SMat Martineau 			chan->sdu_len = 0;
37830a708f8fSGustavo F. Padovan 		}
37840a708f8fSGustavo F. Padovan 		break;
37850a708f8fSGustavo F. Padovan 	}
37860a708f8fSGustavo F. Padovan 
378784084a31SMat Martineau 	if (err) {
37880a708f8fSGustavo F. Padovan 		kfree_skb(skb);
37896f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
37906f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
379184084a31SMat Martineau 		chan->sdu_last_frag = NULL;
379284084a31SMat Martineau 		chan->sdu_len = 0;
379384084a31SMat Martineau 	}
37940a708f8fSGustavo F. Padovan 
379584084a31SMat Martineau 	return err;
37960a708f8fSGustavo F. Padovan }
37970a708f8fSGustavo F. Padovan 
379826f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
37990a708f8fSGustavo F. Padovan {
380026f880d2SMat Martineau 	BT_DBG("chan %p, Enter local busy", chan);
380126f880d2SMat Martineau 
380226f880d2SMat Martineau 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
380326f880d2SMat Martineau 
380477f918bcSSzymon Janc 	__set_ack_timer(chan);
38050a708f8fSGustavo F. Padovan }
38060a708f8fSGustavo F. Padovan 
380726f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
380826f880d2SMat Martineau {
380988843ab0SAndrei Emeltchenko 	u32 control;
38100a708f8fSGustavo F. Padovan 
3811e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
38120a708f8fSGustavo F. Padovan 		goto done;
38130a708f8fSGustavo F. Padovan 
38140b209faeSAndrei Emeltchenko 	control = __set_reqseq(chan, chan->buffer_seq);
3815e3781735SAndrei Emeltchenko 	control |= __set_ctrl_poll(chan);
3816ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3817525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
38186a026610SGustavo F. Padovan 	chan->retry_count = 1;
38190a708f8fSGustavo F. Padovan 
38201a09bcb9SGustavo F. Padovan 	__clear_retrans_timer(chan);
38211a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
38220a708f8fSGustavo F. Padovan 
3823e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
38240a708f8fSGustavo F. Padovan 
38250a708f8fSGustavo F. Padovan done:
3826e2ab4353SGustavo F. Padovan 	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
3827e2ab4353SGustavo F. Padovan 	clear_bit(CONN_RNR_SENT, &chan->conn_state);
38280a708f8fSGustavo F. Padovan 
382949208c9cSGustavo F. Padovan 	BT_DBG("chan %p, Exit local busy", chan);
38300a708f8fSGustavo F. Padovan }
38310a708f8fSGustavo F. Padovan 
3832e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
38330a708f8fSGustavo F. Padovan {
3834e328140fSMat Martineau 	if (chan->mode == L2CAP_MODE_ERTM) {
3835e328140fSMat Martineau 		if (busy)
383626f880d2SMat Martineau 			l2cap_ertm_enter_local_busy(chan);
3837e328140fSMat Martineau 		else
3838e328140fSMat Martineau 			l2cap_ertm_exit_local_busy(chan);
38390a708f8fSGustavo F. Padovan 	}
38400a708f8fSGustavo F. Padovan }
38410a708f8fSGustavo F. Padovan 
3842fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
38430a708f8fSGustavo F. Padovan {
38440a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
384588843ab0SAndrei Emeltchenko 	u32 control;
38460a708f8fSGustavo F. Padovan 
3847e328140fSMat Martineau 	while ((skb = skb_peek(&chan->srej_q)) &&
3848e328140fSMat Martineau 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3849e328140fSMat Martineau 		int err;
3850e328140fSMat Martineau 
38510a708f8fSGustavo F. Padovan 		if (bt_cb(skb)->tx_seq != tx_seq)
38520a708f8fSGustavo F. Padovan 			break;
38530a708f8fSGustavo F. Padovan 
3854f1c6775bSGustavo F. Padovan 		skb = skb_dequeue(&chan->srej_q);
38557e0ef6eeSAndrei Emeltchenko 		control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
385684084a31SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, control);
3857e328140fSMat Martineau 
3858e328140fSMat Martineau 		if (err < 0) {
3859e328140fSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
3860e328140fSMat Martineau 			break;
3861e328140fSMat Martineau 		}
3862e328140fSMat Martineau 
3863836be934SAndrei Emeltchenko 		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
3864836be934SAndrei Emeltchenko 		tx_seq = __next_seq(chan, tx_seq);
38650a708f8fSGustavo F. Padovan 	}
38660a708f8fSGustavo F. Padovan }
38670a708f8fSGustavo F. Padovan 
3868fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
38690a708f8fSGustavo F. Padovan {
38700a708f8fSGustavo F. Padovan 	struct srej_list *l, *tmp;
387188843ab0SAndrei Emeltchenko 	u32 control;
38720a708f8fSGustavo F. Padovan 
387339d5a3eeSGustavo F. Padovan 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
38740a708f8fSGustavo F. Padovan 		if (l->tx_seq == tx_seq) {
38750a708f8fSGustavo F. Padovan 			list_del(&l->list);
38760a708f8fSGustavo F. Padovan 			kfree(l);
38770a708f8fSGustavo F. Padovan 			return;
38780a708f8fSGustavo F. Padovan 		}
3879ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
38800b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, l->tx_seq);
3881525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
38820a708f8fSGustavo F. Padovan 		list_del(&l->list);
388339d5a3eeSGustavo F. Padovan 		list_add_tail(&l->list, &chan->srej_l);
38840a708f8fSGustavo F. Padovan 	}
38850a708f8fSGustavo F. Padovan }
38860a708f8fSGustavo F. Padovan 
3887aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
38880a708f8fSGustavo F. Padovan {
38890a708f8fSGustavo F. Padovan 	struct srej_list *new;
389088843ab0SAndrei Emeltchenko 	u32 control;
38910a708f8fSGustavo F. Padovan 
389242e5c802SGustavo F. Padovan 	while (tx_seq != chan->expected_tx_seq) {
3893ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
38940b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->expected_tx_seq);
3895525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
38960a708f8fSGustavo F. Padovan 
38970a708f8fSGustavo F. Padovan 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
3898aef89f21SSzymon Janc 		if (!new)
3899aef89f21SSzymon Janc 			return -ENOMEM;
3900aef89f21SSzymon Janc 
390142e5c802SGustavo F. Padovan 		new->tx_seq = chan->expected_tx_seq;
3902836be934SAndrei Emeltchenko 
3903836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3904836be934SAndrei Emeltchenko 
390539d5a3eeSGustavo F. Padovan 		list_add_tail(&new->list, &chan->srej_l);
39060a708f8fSGustavo F. Padovan 	}
3907836be934SAndrei Emeltchenko 
3908836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
3909aef89f21SSzymon Janc 
3910aef89f21SSzymon Janc 	return 0;
39110a708f8fSGustavo F. Padovan }
39120a708f8fSGustavo F. Padovan 
391388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
39140a708f8fSGustavo F. Padovan {
3915fb45de7dSAndrei Emeltchenko 	u16 tx_seq = __get_txseq(chan, rx_control);
39160b209faeSAndrei Emeltchenko 	u16 req_seq = __get_reqseq(chan, rx_control);
39177e0ef6eeSAndrei Emeltchenko 	u8 sar = __get_ctrl_sar(chan, rx_control);
39180a708f8fSGustavo F. Padovan 	int tx_seq_offset, expected_tx_seq_offset;
391947d1ec61SGustavo F. Padovan 	int num_to_ack = (chan->tx_win/6) + 1;
39200a708f8fSGustavo F. Padovan 	int err = 0;
39210a708f8fSGustavo F. Padovan 
392288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
3923525cd185SGustavo F. Padovan 							tx_seq, rx_control);
39240a708f8fSGustavo F. Padovan 
392503f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
3926e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
39271a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
39286a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
39291a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
3930e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
39310a708f8fSGustavo F. Padovan 	}
39320a708f8fSGustavo F. Padovan 
393342e5c802SGustavo F. Padovan 	chan->expected_ack_seq = req_seq;
393442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
39350a708f8fSGustavo F. Padovan 
3936836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
39370a708f8fSGustavo F. Padovan 
39380a708f8fSGustavo F. Padovan 	/* invalid tx_seq */
393947d1ec61SGustavo F. Padovan 	if (tx_seq_offset >= chan->tx_win) {
39408c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
39410a708f8fSGustavo F. Padovan 		goto drop;
39420a708f8fSGustavo F. Padovan 	}
39430a708f8fSGustavo F. Padovan 
394477f918bcSSzymon Janc 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
394577f918bcSSzymon Janc 		if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
394677f918bcSSzymon Janc 			l2cap_send_ack(chan);
39470a708f8fSGustavo F. Padovan 		goto drop;
394877f918bcSSzymon Janc 	}
39490a708f8fSGustavo F. Padovan 
395002f1b641SMat Martineau 	if (tx_seq == chan->expected_tx_seq)
395102f1b641SMat Martineau 		goto expected;
395202f1b641SMat Martineau 
3953e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
39540a708f8fSGustavo F. Padovan 		struct srej_list *first;
39550a708f8fSGustavo F. Padovan 
395639d5a3eeSGustavo F. Padovan 		first = list_first_entry(&chan->srej_l,
39570a708f8fSGustavo F. Padovan 				struct srej_list, list);
39580a708f8fSGustavo F. Padovan 		if (tx_seq == first->tx_seq) {
395942e5c802SGustavo F. Padovan 			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
3960525cd185SGustavo F. Padovan 			l2cap_check_srej_gap(chan, tx_seq);
39610a708f8fSGustavo F. Padovan 
39620a708f8fSGustavo F. Padovan 			list_del(&first->list);
39630a708f8fSGustavo F. Padovan 			kfree(first);
39640a708f8fSGustavo F. Padovan 
396539d5a3eeSGustavo F. Padovan 			if (list_empty(&chan->srej_l)) {
396642e5c802SGustavo F. Padovan 				chan->buffer_seq = chan->buffer_seq_srej;
3967e2ab4353SGustavo F. Padovan 				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
3968525cd185SGustavo F. Padovan 				l2cap_send_ack(chan);
396949208c9cSGustavo F. Padovan 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
39700a708f8fSGustavo F. Padovan 			}
39710a708f8fSGustavo F. Padovan 		} else {
39720a708f8fSGustavo F. Padovan 			struct srej_list *l;
39730a708f8fSGustavo F. Padovan 
39740a708f8fSGustavo F. Padovan 			/* duplicated tx_seq */
397542e5c802SGustavo F. Padovan 			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
39760a708f8fSGustavo F. Padovan 				goto drop;
39770a708f8fSGustavo F. Padovan 
397839d5a3eeSGustavo F. Padovan 			list_for_each_entry(l, &chan->srej_l, list) {
39790a708f8fSGustavo F. Padovan 				if (l->tx_seq == tx_seq) {
3980525cd185SGustavo F. Padovan 					l2cap_resend_srejframe(chan, tx_seq);
39810a708f8fSGustavo F. Padovan 					return 0;
39820a708f8fSGustavo F. Padovan 				}
39830a708f8fSGustavo F. Padovan 			}
3984aef89f21SSzymon Janc 
3985aef89f21SSzymon Janc 			err = l2cap_send_srejframe(chan, tx_seq);
3986aef89f21SSzymon Janc 			if (err < 0) {
3987aef89f21SSzymon Janc 				l2cap_send_disconn_req(chan->conn, chan, -err);
3988aef89f21SSzymon Janc 				return err;
3989aef89f21SSzymon Janc 			}
39900a708f8fSGustavo F. Padovan 		}
39910a708f8fSGustavo F. Padovan 	} else {
3992836be934SAndrei Emeltchenko 		expected_tx_seq_offset = __seq_offset(chan,
3993836be934SAndrei Emeltchenko 				chan->expected_tx_seq, chan->buffer_seq);
39940a708f8fSGustavo F. Padovan 
39950a708f8fSGustavo F. Padovan 		/* duplicated tx_seq */
39960a708f8fSGustavo F. Padovan 		if (tx_seq_offset < expected_tx_seq_offset)
39970a708f8fSGustavo F. Padovan 			goto drop;
39980a708f8fSGustavo F. Padovan 
3999e2ab4353SGustavo F. Padovan 		set_bit(CONN_SREJ_SENT, &chan->conn_state);
40000a708f8fSGustavo F. Padovan 
400149208c9cSGustavo F. Padovan 		BT_DBG("chan %p, Enter SREJ", chan);
40020a708f8fSGustavo F. Padovan 
400339d5a3eeSGustavo F. Padovan 		INIT_LIST_HEAD(&chan->srej_l);
400442e5c802SGustavo F. Padovan 		chan->buffer_seq_srej = chan->buffer_seq;
40050a708f8fSGustavo F. Padovan 
4006f1c6775bSGustavo F. Padovan 		__skb_queue_head_init(&chan->srej_q);
400742e5c802SGustavo F. Padovan 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
40080a708f8fSGustavo F. Padovan 
40090ef3ef0fSSzymon Janc 		/* Set P-bit only if there are some I-frames to ack. */
40100ef3ef0fSSzymon Janc 		if (__clear_ack_timer(chan))
4011e2ab4353SGustavo F. Padovan 			set_bit(CONN_SEND_PBIT, &chan->conn_state);
40120a708f8fSGustavo F. Padovan 
4013aef89f21SSzymon Janc 		err = l2cap_send_srejframe(chan, tx_seq);
4014aef89f21SSzymon Janc 		if (err < 0) {
4015aef89f21SSzymon Janc 			l2cap_send_disconn_req(chan->conn, chan, -err);
4016aef89f21SSzymon Janc 			return err;
4017aef89f21SSzymon Janc 		}
40180a708f8fSGustavo F. Padovan 	}
40190a708f8fSGustavo F. Padovan 	return 0;
40200a708f8fSGustavo F. Padovan 
40210a708f8fSGustavo F. Padovan expected:
4022836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
40230a708f8fSGustavo F. Padovan 
4024e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
40250a708f8fSGustavo F. Padovan 		bt_cb(skb)->tx_seq = tx_seq;
40260a708f8fSGustavo F. Padovan 		bt_cb(skb)->sar = sar;
4027f1c6775bSGustavo F. Padovan 		__skb_queue_tail(&chan->srej_q, skb);
40280a708f8fSGustavo F. Padovan 		return 0;
40290a708f8fSGustavo F. Padovan 	}
40300a708f8fSGustavo F. Padovan 
403184084a31SMat Martineau 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
4032836be934SAndrei Emeltchenko 	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4033836be934SAndrei Emeltchenko 
4034e328140fSMat Martineau 	if (err < 0) {
4035e328140fSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4036e328140fSMat Martineau 		return err;
4037e328140fSMat Martineau 	}
40380a708f8fSGustavo F. Padovan 
403903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4040e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4041525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
40420a708f8fSGustavo F. Padovan 	}
40430a708f8fSGustavo F. Padovan 
40440a708f8fSGustavo F. Padovan 
40456a026610SGustavo F. Padovan 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
40466a026610SGustavo F. Padovan 	if (chan->num_acked == num_to_ack - 1)
4047525cd185SGustavo F. Padovan 		l2cap_send_ack(chan);
40484d611e4dSGustavo F. Padovan 	else
40494d611e4dSGustavo F. Padovan 		__set_ack_timer(chan);
40500a708f8fSGustavo F. Padovan 
40510a708f8fSGustavo F. Padovan 	return 0;
40520a708f8fSGustavo F. Padovan 
40530a708f8fSGustavo F. Padovan drop:
40540a708f8fSGustavo F. Padovan 	kfree_skb(skb);
40550a708f8fSGustavo F. Padovan 	return 0;
40560a708f8fSGustavo F. Padovan }
40570a708f8fSGustavo F. Padovan 
405888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
40590a708f8fSGustavo F. Padovan {
406088843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
40610b209faeSAndrei Emeltchenko 				__get_reqseq(chan, rx_control), rx_control);
40620a708f8fSGustavo F. Padovan 
40630b209faeSAndrei Emeltchenko 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
406442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
40650a708f8fSGustavo F. Padovan 
4066e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4067e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4068e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4069e2ab4353SGustavo F. Padovan 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
40706a026610SGustavo F. Padovan 					(chan->unacked_frames > 0))
40711a09bcb9SGustavo F. Padovan 				__set_retrans_timer(chan);
40720a708f8fSGustavo F. Padovan 
4073e2ab4353SGustavo F. Padovan 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4074525cd185SGustavo F. Padovan 			l2cap_send_srejtail(chan);
40750a708f8fSGustavo F. Padovan 		} else {
4076525cd185SGustavo F. Padovan 			l2cap_send_i_or_rr_or_rnr(chan);
40770a708f8fSGustavo F. Padovan 		}
40780a708f8fSGustavo F. Padovan 
407903f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4080e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
40810a708f8fSGustavo F. Padovan 
4082e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4083525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
40840a708f8fSGustavo F. Padovan 
40850a708f8fSGustavo F. Padovan 	} else {
4086e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
40876a026610SGustavo F. Padovan 				(chan->unacked_frames > 0))
40881a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
40890a708f8fSGustavo F. Padovan 
4090e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4091e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
4092525cd185SGustavo F. Padovan 			l2cap_send_ack(chan);
40930a708f8fSGustavo F. Padovan 		else
4094525cd185SGustavo F. Padovan 			l2cap_ertm_send(chan);
40950a708f8fSGustavo F. Padovan 	}
40960a708f8fSGustavo F. Padovan }
40970a708f8fSGustavo F. Padovan 
409888843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
40990a708f8fSGustavo F. Padovan {
41000b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
41010a708f8fSGustavo F. Padovan 
410288843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
41030a708f8fSGustavo F. Padovan 
4104e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
41050a708f8fSGustavo F. Padovan 
410642e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
410742e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
41080a708f8fSGustavo F. Padovan 
410903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4110e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4111525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
41120a708f8fSGustavo F. Padovan 	} else {
4113525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
41140a708f8fSGustavo F. Padovan 
4115e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state))
4116e2ab4353SGustavo F. Padovan 			set_bit(CONN_REJ_ACT, &chan->conn_state);
41170a708f8fSGustavo F. Padovan 	}
41180a708f8fSGustavo F. Padovan }
411988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
41200a708f8fSGustavo F. Padovan {
41210b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
41220a708f8fSGustavo F. Padovan 
412388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
41240a708f8fSGustavo F. Padovan 
4125e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
41260a708f8fSGustavo F. Padovan 
4127e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
412842e5c802SGustavo F. Padovan 		chan->expected_ack_seq = tx_seq;
412942e5c802SGustavo F. Padovan 		l2cap_drop_acked_frames(chan);
41300a708f8fSGustavo F. Padovan 
4131e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4132525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
41330a708f8fSGustavo F. Padovan 
4134525cd185SGustavo F. Padovan 		l2cap_ertm_send(chan);
41350a708f8fSGustavo F. Padovan 
4136e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
41376a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4138e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
41390a708f8fSGustavo F. Padovan 		}
414003f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4141e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
41426a026610SGustavo F. Padovan 				chan->srej_save_reqseq == tx_seq)
4143e2ab4353SGustavo F. Padovan 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
41440a708f8fSGustavo F. Padovan 		else
4145525cd185SGustavo F. Padovan 			l2cap_retransmit_one_frame(chan, tx_seq);
41460a708f8fSGustavo F. Padovan 	} else {
4147525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
4148e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
41496a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4150e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
41510a708f8fSGustavo F. Padovan 		}
41520a708f8fSGustavo F. Padovan 	}
41530a708f8fSGustavo F. Padovan }
41540a708f8fSGustavo F. Padovan 
415588843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
41560a708f8fSGustavo F. Padovan {
41570b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
41580a708f8fSGustavo F. Padovan 
415988843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
41600a708f8fSGustavo F. Padovan 
4161e2ab4353SGustavo F. Padovan 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
416242e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
416342e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
41640a708f8fSGustavo F. Padovan 
4165e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control))
4166e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
41670a708f8fSGustavo F. Padovan 
4168e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
41691a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4170e3781735SAndrei Emeltchenko 		if (__is_ctrl_poll(chan, rx_control))
4171525cd185SGustavo F. Padovan 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
41720a708f8fSGustavo F. Padovan 		return;
41730a708f8fSGustavo F. Padovan 	}
41740a708f8fSGustavo F. Padovan 
4175e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4176525cd185SGustavo F. Padovan 		l2cap_send_srejtail(chan);
4177ab784b73SAndrei Emeltchenko 	} else {
4178ab784b73SAndrei Emeltchenko 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4179ab784b73SAndrei Emeltchenko 		l2cap_send_sframe(chan, rx_control);
4180ab784b73SAndrei Emeltchenko 	}
41810a708f8fSGustavo F. Padovan }
41820a708f8fSGustavo F. Padovan 
418388843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
41840a708f8fSGustavo F. Padovan {
418588843ab0SAndrei Emeltchenko 	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
41860a708f8fSGustavo F. Padovan 
418703f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4188e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
41891a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
41906a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
41911a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4192e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
41930a708f8fSGustavo F. Padovan 	}
41940a708f8fSGustavo F. Padovan 
4195ab784b73SAndrei Emeltchenko 	switch (__get_ctrl_super(chan, rx_control)) {
4196ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RR:
4197525cd185SGustavo F. Padovan 		l2cap_data_channel_rrframe(chan, rx_control);
41980a708f8fSGustavo F. Padovan 		break;
41990a708f8fSGustavo F. Padovan 
4200ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_REJ:
4201525cd185SGustavo F. Padovan 		l2cap_data_channel_rejframe(chan, rx_control);
42020a708f8fSGustavo F. Padovan 		break;
42030a708f8fSGustavo F. Padovan 
4204ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_SREJ:
4205525cd185SGustavo F. Padovan 		l2cap_data_channel_srejframe(chan, rx_control);
42060a708f8fSGustavo F. Padovan 		break;
42070a708f8fSGustavo F. Padovan 
4208ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RNR:
4209525cd185SGustavo F. Padovan 		l2cap_data_channel_rnrframe(chan, rx_control);
42100a708f8fSGustavo F. Padovan 		break;
42110a708f8fSGustavo F. Padovan 	}
42120a708f8fSGustavo F. Padovan 
42130a708f8fSGustavo F. Padovan 	kfree_skb(skb);
42140a708f8fSGustavo F. Padovan 	return 0;
42150a708f8fSGustavo F. Padovan }
42160a708f8fSGustavo F. Padovan 
4217cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
42180a708f8fSGustavo F. Padovan {
421988843ab0SAndrei Emeltchenko 	u32 control;
42200b209faeSAndrei Emeltchenko 	u16 req_seq;
42210a708f8fSGustavo F. Padovan 	int len, next_tx_seq_offset, req_seq_offset;
42220a708f8fSGustavo F. Padovan 
422388843ab0SAndrei Emeltchenko 	control = __get_control(chan, skb->data);
422488843ab0SAndrei Emeltchenko 	skb_pull(skb, __ctrl_size(chan));
42250a708f8fSGustavo F. Padovan 	len = skb->len;
42260a708f8fSGustavo F. Padovan 
42270a708f8fSGustavo F. Padovan 	/*
42280a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
42290a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
42300a708f8fSGustavo F. Padovan 	 * procedures and ask retransmission.
42310a708f8fSGustavo F. Padovan 	 */
423247d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
42330a708f8fSGustavo F. Padovan 		goto drop;
42340a708f8fSGustavo F. Padovan 
4235793c2f1cSAndrei Emeltchenko 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
423603a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
42370a708f8fSGustavo F. Padovan 
423847d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
423903a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
42400a708f8fSGustavo F. Padovan 
424147d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
42428c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42430a708f8fSGustavo F. Padovan 		goto drop;
42440a708f8fSGustavo F. Padovan 	}
42450a708f8fSGustavo F. Padovan 
42460b209faeSAndrei Emeltchenko 	req_seq = __get_reqseq(chan, control);
42470a708f8fSGustavo F. Padovan 
4248836be934SAndrei Emeltchenko 	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4249836be934SAndrei Emeltchenko 
4250836be934SAndrei Emeltchenko 	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4251836be934SAndrei Emeltchenko 						chan->expected_ack_seq);
42520a708f8fSGustavo F. Padovan 
42530a708f8fSGustavo F. Padovan 	/* check for invalid req-seq */
42540a708f8fSGustavo F. Padovan 	if (req_seq_offset > next_tx_seq_offset) {
42558c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42560a708f8fSGustavo F. Padovan 		goto drop;
42570a708f8fSGustavo F. Padovan 	}
42580a708f8fSGustavo F. Padovan 
4259793c2f1cSAndrei Emeltchenko 	if (!__is_sframe(chan, control)) {
42600a708f8fSGustavo F. Padovan 		if (len < 0) {
42618c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42620a708f8fSGustavo F. Padovan 			goto drop;
42630a708f8fSGustavo F. Padovan 		}
42640a708f8fSGustavo F. Padovan 
4265525cd185SGustavo F. Padovan 		l2cap_data_channel_iframe(chan, control, skb);
42660a708f8fSGustavo F. Padovan 	} else {
42670a708f8fSGustavo F. Padovan 		if (len != 0) {
42680a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
42698c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42700a708f8fSGustavo F. Padovan 			goto drop;
42710a708f8fSGustavo F. Padovan 		}
42720a708f8fSGustavo F. Padovan 
4273525cd185SGustavo F. Padovan 		l2cap_data_channel_sframe(chan, control, skb);
42740a708f8fSGustavo F. Padovan 	}
42750a708f8fSGustavo F. Padovan 
42760a708f8fSGustavo F. Padovan 	return 0;
42770a708f8fSGustavo F. Padovan 
42780a708f8fSGustavo F. Padovan drop:
42790a708f8fSGustavo F. Padovan 	kfree_skb(skb);
42800a708f8fSGustavo F. Padovan 	return 0;
42810a708f8fSGustavo F. Padovan }
42820a708f8fSGustavo F. Padovan 
42830a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
42840a708f8fSGustavo F. Padovan {
428548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
428688843ab0SAndrei Emeltchenko 	u32 control;
4287fb45de7dSAndrei Emeltchenko 	u16 tx_seq;
42880a708f8fSGustavo F. Padovan 	int len;
42890a708f8fSGustavo F. Padovan 
4290baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
429148454079SGustavo F. Padovan 	if (!chan) {
42920a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
42936be36555SAndrei Emeltchenko 		/* Drop packet and return */
42943379013bSDan Carpenter 		kfree_skb(skb);
42956be36555SAndrei Emeltchenko 		return 0;
42960a708f8fSGustavo F. Padovan 	}
42970a708f8fSGustavo F. Padovan 
42986be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
42990a708f8fSGustavo F. Padovan 
430049208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
43010a708f8fSGustavo F. Padovan 
430289bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
43030a708f8fSGustavo F. Padovan 		goto drop;
43040a708f8fSGustavo F. Padovan 
43050c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
43060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
43070a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
43080a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
43090a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
43100a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
43110a708f8fSGustavo F. Padovan 
43120c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
43130a708f8fSGustavo F. Padovan 			goto drop;
43140a708f8fSGustavo F. Padovan 
431523070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
43160a708f8fSGustavo F. Padovan 			goto done;
43170a708f8fSGustavo F. Padovan 		break;
43180a708f8fSGustavo F. Padovan 
43190a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
43205ef8cb9eSAndrei Emeltchenko 		l2cap_ertm_data_rcv(chan, skb);
43210a708f8fSGustavo F. Padovan 
43220a708f8fSGustavo F. Padovan 		goto done;
43230a708f8fSGustavo F. Padovan 
43240a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
432588843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data);
432688843ab0SAndrei Emeltchenko 		skb_pull(skb, __ctrl_size(chan));
43270a708f8fSGustavo F. Padovan 		len = skb->len;
43280a708f8fSGustavo F. Padovan 
432947d1ec61SGustavo F. Padovan 		if (l2cap_check_fcs(chan, skb))
43300a708f8fSGustavo F. Padovan 			goto drop;
43310a708f8fSGustavo F. Padovan 
43327e0ef6eeSAndrei Emeltchenko 		if (__is_sar_start(chan, control))
433303a51213SAndrei Emeltchenko 			len -= L2CAP_SDULEN_SIZE;
43340a708f8fSGustavo F. Padovan 
433547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16)
433603a51213SAndrei Emeltchenko 			len -= L2CAP_FCS_SIZE;
43370a708f8fSGustavo F. Padovan 
4338793c2f1cSAndrei Emeltchenko 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
43390a708f8fSGustavo F. Padovan 			goto drop;
43400a708f8fSGustavo F. Padovan 
4341fb45de7dSAndrei Emeltchenko 		tx_seq = __get_txseq(chan, control);
43420a708f8fSGustavo F. Padovan 
434384084a31SMat Martineau 		if (chan->expected_tx_seq != tx_seq) {
434484084a31SMat Martineau 			/* Frame(s) missing - must discard partial SDU */
434584084a31SMat Martineau 			kfree_skb(chan->sdu);
434684084a31SMat Martineau 			chan->sdu = NULL;
434784084a31SMat Martineau 			chan->sdu_last_frag = NULL;
434884084a31SMat Martineau 			chan->sdu_len = 0;
434984084a31SMat Martineau 
435084084a31SMat Martineau 			/* TODO: Notify userland of missing data */
435184084a31SMat Martineau 		}
435284084a31SMat Martineau 
4353836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, tx_seq);
43540a708f8fSGustavo F. Padovan 
435584084a31SMat Martineau 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
435684084a31SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
43570a708f8fSGustavo F. Padovan 
43580a708f8fSGustavo F. Padovan 		goto done;
43590a708f8fSGustavo F. Padovan 
43600a708f8fSGustavo F. Padovan 	default:
43610c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
43620a708f8fSGustavo F. Padovan 		break;
43630a708f8fSGustavo F. Padovan 	}
43640a708f8fSGustavo F. Padovan 
43650a708f8fSGustavo F. Padovan drop:
43660a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43670a708f8fSGustavo F. Padovan 
43680a708f8fSGustavo F. Padovan done:
43696be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43700a708f8fSGustavo F. Padovan 
43710a708f8fSGustavo F. Padovan 	return 0;
43720a708f8fSGustavo F. Padovan }
43730a708f8fSGustavo F. Padovan 
43740a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
43750a708f8fSGustavo F. Padovan {
437623691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
43770a708f8fSGustavo F. Padovan 
437823691d75SGustavo F. Padovan 	chan = l2cap_global_chan_by_psm(0, psm, conn->src);
437923691d75SGustavo F. Padovan 	if (!chan)
43800a708f8fSGustavo F. Padovan 		goto drop;
43810a708f8fSGustavo F. Padovan 
43825b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
43830a708f8fSGustavo F. Padovan 
438489bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
43850a708f8fSGustavo F. Padovan 		goto drop;
43860a708f8fSGustavo F. Padovan 
4387e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
43880a708f8fSGustavo F. Padovan 		goto drop;
43890a708f8fSGustavo F. Padovan 
439023070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
43915b4cedaaSAndrei Emeltchenko 		return 0;
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan drop:
43940a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43950a708f8fSGustavo F. Padovan 
43960a708f8fSGustavo F. Padovan 	return 0;
43970a708f8fSGustavo F. Padovan }
43980a708f8fSGustavo F. Padovan 
43999f69bda6SGustavo F. Padovan static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
44009f69bda6SGustavo F. Padovan {
440123691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
44029f69bda6SGustavo F. Padovan 
440323691d75SGustavo F. Padovan 	chan = l2cap_global_chan_by_scid(0, cid, conn->src);
440423691d75SGustavo F. Padovan 	if (!chan)
44059f69bda6SGustavo F. Padovan 		goto drop;
44069f69bda6SGustavo F. Padovan 
44075b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
44089f69bda6SGustavo F. Padovan 
440989bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
44109f69bda6SGustavo F. Padovan 		goto drop;
44119f69bda6SGustavo F. Padovan 
4412e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
44139f69bda6SGustavo F. Padovan 		goto drop;
44149f69bda6SGustavo F. Padovan 
441523070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
44165b4cedaaSAndrei Emeltchenko 		return 0;
44179f69bda6SGustavo F. Padovan 
44189f69bda6SGustavo F. Padovan drop:
44199f69bda6SGustavo F. Padovan 	kfree_skb(skb);
44209f69bda6SGustavo F. Padovan 
44219f69bda6SGustavo F. Padovan 	return 0;
44229f69bda6SGustavo F. Padovan }
44239f69bda6SGustavo F. Padovan 
44240a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
44250a708f8fSGustavo F. Padovan {
44260a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
44270a708f8fSGustavo F. Padovan 	u16 cid, len;
44280a708f8fSGustavo F. Padovan 	__le16 psm;
44290a708f8fSGustavo F. Padovan 
44300a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
44310a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
44320a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
44330a708f8fSGustavo F. Padovan 
44340a708f8fSGustavo F. Padovan 	if (len != skb->len) {
44350a708f8fSGustavo F. Padovan 		kfree_skb(skb);
44360a708f8fSGustavo F. Padovan 		return;
44370a708f8fSGustavo F. Padovan 	}
44380a708f8fSGustavo F. Padovan 
44390a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
44400a708f8fSGustavo F. Padovan 
44410a708f8fSGustavo F. Padovan 	switch (cid) {
44423300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
44430a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
44440a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
44450a708f8fSGustavo F. Padovan 		break;
44460a708f8fSGustavo F. Padovan 
44470a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4448097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
44490a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
44500a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
44510a708f8fSGustavo F. Padovan 		break;
44520a708f8fSGustavo F. Padovan 
44539f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
44549f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
44559f69bda6SGustavo F. Padovan 		break;
44569f69bda6SGustavo F. Padovan 
4457b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4458b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4459b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4460b501d6a1SAnderson Briglia 		break;
4461b501d6a1SAnderson Briglia 
44620a708f8fSGustavo F. Padovan 	default:
44630a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
44640a708f8fSGustavo F. Padovan 		break;
44650a708f8fSGustavo F. Padovan 	}
44660a708f8fSGustavo F. Padovan }
44670a708f8fSGustavo F. Padovan 
44680a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
44690a708f8fSGustavo F. Padovan 
4470686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
44710a708f8fSGustavo F. Padovan {
44720a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
447323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
44740a708f8fSGustavo F. Padovan 
44750a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
44760a708f8fSGustavo F. Padovan 
44770a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
447823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
447923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
448023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
44814343478fSGustavo F. Padovan 
448289bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
44830a708f8fSGustavo F. Padovan 			continue;
44840a708f8fSGustavo F. Padovan 
44850a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
44860a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
448743bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
44880a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
44890a708f8fSGustavo F. Padovan 			exact++;
44900a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
44910a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
449243bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
44930a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
44940a708f8fSGustavo F. Padovan 		}
44950a708f8fSGustavo F. Padovan 	}
449623691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
44970a708f8fSGustavo F. Padovan 
44980a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
44990a708f8fSGustavo F. Padovan }
45000a708f8fSGustavo F. Padovan 
4501686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
45020a708f8fSGustavo F. Padovan {
45030a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
45040a708f8fSGustavo F. Padovan 
45050a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
45060a708f8fSGustavo F. Padovan 
45070a708f8fSGustavo F. Padovan 	if (!status) {
45080a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
45090a708f8fSGustavo F. Padovan 		if (conn)
45100a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
45110a708f8fSGustavo F. Padovan 	} else
4512e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
45130a708f8fSGustavo F. Padovan 
45140a708f8fSGustavo F. Padovan 	return 0;
45150a708f8fSGustavo F. Padovan }
45160a708f8fSGustavo F. Padovan 
4517686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
45180a708f8fSGustavo F. Padovan {
45190a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
45200a708f8fSGustavo F. Padovan 
45210a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
45220a708f8fSGustavo F. Padovan 
4523686ebf28SUlisses Furquim 	if (!conn)
45249f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
45250a708f8fSGustavo F. Padovan 	return conn->disc_reason;
45260a708f8fSGustavo F. Padovan }
45270a708f8fSGustavo F. Padovan 
4528686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
45290a708f8fSGustavo F. Padovan {
45300a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
45310a708f8fSGustavo F. Padovan 
4532e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
45330a708f8fSGustavo F. Padovan 	return 0;
45340a708f8fSGustavo F. Padovan }
45350a708f8fSGustavo F. Padovan 
45364343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
45370a708f8fSGustavo F. Padovan {
4538715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
45390a708f8fSGustavo F. Padovan 		return;
45400a708f8fSGustavo F. Padovan 
45410a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
45424343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4543c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
4544ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
45454343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
45460f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
45470a708f8fSGustavo F. Padovan 	} else {
45484343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4549c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
45500a708f8fSGustavo F. Padovan 	}
45510a708f8fSGustavo F. Padovan }
45520a708f8fSGustavo F. Padovan 
4553686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
45540a708f8fSGustavo F. Padovan {
45550a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
455648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
45570a708f8fSGustavo F. Padovan 
45580a708f8fSGustavo F. Padovan 	if (!conn)
45590a708f8fSGustavo F. Padovan 		return 0;
45600a708f8fSGustavo F. Padovan 
45610a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
45620a708f8fSGustavo F. Padovan 
4563160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
4564160dc6acSVinicius Costa Gomes 		smp_distribute_keys(conn, 0);
456517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4566160dc6acSVinicius Costa Gomes 	}
4567160dc6acSVinicius Costa Gomes 
45683df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
45690a708f8fSGustavo F. Padovan 
45703df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
45716be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
45720a708f8fSGustavo F. Padovan 
4573f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4574f1cb9af5SVinicius Costa Gomes 
4575f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4576f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4577f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4578cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4579f1cb9af5SVinicius Costa Gomes 			}
4580f1cb9af5SVinicius Costa Gomes 
45816be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4582f1cb9af5SVinicius Costa Gomes 			continue;
4583f1cb9af5SVinicius Costa Gomes 		}
4584f1cb9af5SVinicius Costa Gomes 
4585c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
45866be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
45870a708f8fSGustavo F. Padovan 			continue;
45880a708f8fSGustavo F. Padovan 		}
45890a708f8fSGustavo F. Padovan 
459089bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
459189bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
45924343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
45936be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
45940a708f8fSGustavo F. Padovan 			continue;
45950a708f8fSGustavo F. Padovan 		}
45960a708f8fSGustavo F. Padovan 
459789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
45980a708f8fSGustavo F. Padovan 			if (!status) {
45999b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
46000a708f8fSGustavo F. Padovan 			} else {
4601c9b66675SGustavo F. Padovan 				__clear_chan_timer(chan);
4602ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
46030a708f8fSGustavo F. Padovan 			}
460489bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
46056be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
46060a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4607df3c3931SJohan Hedberg 			__u16 res, stat;
46080a708f8fSGustavo F. Padovan 
46096be36555SAndrei Emeltchenko 			lock_sock(sk);
46106be36555SAndrei Emeltchenko 
46110a708f8fSGustavo F. Padovan 			if (!status) {
4612df3c3931SJohan Hedberg 				if (bt_sk(sk)->defer_setup) {
4613df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4614df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4615df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
461605e9a2f6SIlia Kolomisnky 					if (parent)
4617df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4618df3c3931SJohan Hedberg 				} else {
46190e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4620df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4621df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4622df3c3931SJohan Hedberg 				}
46230a708f8fSGustavo F. Padovan 			} else {
46240e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4625ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4626df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4627df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
46280a708f8fSGustavo F. Padovan 			}
46290a708f8fSGustavo F. Padovan 
46306be36555SAndrei Emeltchenko 			release_sock(sk);
46316be36555SAndrei Emeltchenko 
4632fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4633fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4634df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4635df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4636fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4637fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
46380a708f8fSGustavo F. Padovan 		}
46390a708f8fSGustavo F. Padovan 
46406be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
46410a708f8fSGustavo F. Padovan 	}
46420a708f8fSGustavo F. Padovan 
46433df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46440a708f8fSGustavo F. Padovan 
46450a708f8fSGustavo F. Padovan 	return 0;
46460a708f8fSGustavo F. Padovan }
46470a708f8fSGustavo F. Padovan 
4648686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
46490a708f8fSGustavo F. Padovan {
46500a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
46510a708f8fSGustavo F. Padovan 
46520a708f8fSGustavo F. Padovan 	if (!conn)
46530a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
46540a708f8fSGustavo F. Padovan 
46550a708f8fSGustavo F. Padovan 	if (!conn)
46560a708f8fSGustavo F. Padovan 		goto drop;
46570a708f8fSGustavo F. Padovan 
46580a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
46590a708f8fSGustavo F. Padovan 
46600a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
46610a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
466248454079SGustavo F. Padovan 		struct l2cap_chan *chan;
46630a708f8fSGustavo F. Padovan 		u16 cid;
46640a708f8fSGustavo F. Padovan 		int len;
46650a708f8fSGustavo F. Padovan 
46660a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
46670a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
46680a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
46690a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
46700a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
46710a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
46720a708f8fSGustavo F. Padovan 		}
46730a708f8fSGustavo F. Padovan 
46740a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
46750a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
46760a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
46770a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
46780a708f8fSGustavo F. Padovan 			goto drop;
46790a708f8fSGustavo F. Padovan 		}
46800a708f8fSGustavo F. Padovan 
46810a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
46820a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
46830a708f8fSGustavo F. Padovan 		cid = __le16_to_cpu(hdr->cid);
46840a708f8fSGustavo F. Padovan 
46850a708f8fSGustavo F. Padovan 		if (len == skb->len) {
46860a708f8fSGustavo F. Padovan 			/* Complete frame received */
46870a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
46880a708f8fSGustavo F. Padovan 			return 0;
46890a708f8fSGustavo F. Padovan 		}
46900a708f8fSGustavo F. Padovan 
46910a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
46920a708f8fSGustavo F. Padovan 
46930a708f8fSGustavo F. Padovan 		if (skb->len > len) {
46940a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
46950a708f8fSGustavo F. Padovan 				skb->len, len);
46960a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
46970a708f8fSGustavo F. Padovan 			goto drop;
46980a708f8fSGustavo F. Padovan 		}
46990a708f8fSGustavo F. Padovan 
4700baa7e1faSGustavo F. Padovan 		chan = l2cap_get_chan_by_scid(conn, cid);
47010a708f8fSGustavo F. Padovan 
470248454079SGustavo F. Padovan 		if (chan && chan->sk) {
470348454079SGustavo F. Padovan 			struct sock *sk = chan->sk;
47043df91ea2SAndrei Emeltchenko 			lock_sock(sk);
470548454079SGustavo F. Padovan 
47060c1bc5c6SGustavo F. Padovan 			if (chan->imtu < len - L2CAP_HDR_SIZE) {
470748454079SGustavo F. Padovan 				BT_ERR("Frame exceeding recv MTU (len %d, "
470848454079SGustavo F. Padovan 							"MTU %d)", len,
47090c1bc5c6SGustavo F. Padovan 							chan->imtu);
4710aa2ac881SGustavo F. Padovan 				release_sock(sk);
47110a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
47120a708f8fSGustavo F. Padovan 				goto drop;
47130a708f8fSGustavo F. Padovan 			}
4714aa2ac881SGustavo F. Padovan 			release_sock(sk);
471548454079SGustavo F. Padovan 		}
47160a708f8fSGustavo F. Padovan 
47170a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
47180a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
47190a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
47200a708f8fSGustavo F. Padovan 			goto drop;
47210a708f8fSGustavo F. Padovan 
47220a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
47230a708f8fSGustavo F. Padovan 								skb->len);
47240a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
47250a708f8fSGustavo F. Padovan 	} else {
47260a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
47270a708f8fSGustavo F. Padovan 
47280a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
47290a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
47300a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
47310a708f8fSGustavo F. Padovan 			goto drop;
47320a708f8fSGustavo F. Padovan 		}
47330a708f8fSGustavo F. Padovan 
47340a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
47350a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
47360a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
47370a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
47380a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
47390a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
47400a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
47410a708f8fSGustavo F. Padovan 			goto drop;
47420a708f8fSGustavo F. Padovan 		}
47430a708f8fSGustavo F. Padovan 
47440a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
47450a708f8fSGustavo F. Padovan 								skb->len);
47460a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
47470a708f8fSGustavo F. Padovan 
47480a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
47490a708f8fSGustavo F. Padovan 			/* Complete frame received */
47500a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
47510a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
47520a708f8fSGustavo F. Padovan 		}
47530a708f8fSGustavo F. Padovan 	}
47540a708f8fSGustavo F. Padovan 
47550a708f8fSGustavo F. Padovan drop:
47560a708f8fSGustavo F. Padovan 	kfree_skb(skb);
47570a708f8fSGustavo F. Padovan 	return 0;
47580a708f8fSGustavo F. Padovan }
47590a708f8fSGustavo F. Padovan 
47600a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
47610a708f8fSGustavo F. Padovan {
476223691d75SGustavo F. Padovan 	struct l2cap_chan *c;
47630a708f8fSGustavo F. Padovan 
4764333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
47650a708f8fSGustavo F. Padovan 
476623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
476723691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
47680a708f8fSGustavo F. Padovan 
4769903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
47700a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
47710a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
477289bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
477323691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
477423691d75SGustavo F. Padovan 					c->sec_level, c->mode);
47750a708f8fSGustavo F. Padovan 	}
47760a708f8fSGustavo F. Padovan 
4777333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
47780a708f8fSGustavo F. Padovan 
47790a708f8fSGustavo F. Padovan 	return 0;
47800a708f8fSGustavo F. Padovan }
47810a708f8fSGustavo F. Padovan 
47820a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
47830a708f8fSGustavo F. Padovan {
47840a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
47850a708f8fSGustavo F. Padovan }
47860a708f8fSGustavo F. Padovan 
47870a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
47880a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
47890a708f8fSGustavo F. Padovan 	.read		= seq_read,
47900a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
47910a708f8fSGustavo F. Padovan 	.release	= single_release,
47920a708f8fSGustavo F. Padovan };
47930a708f8fSGustavo F. Padovan 
47940a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
47950a708f8fSGustavo F. Padovan 
479664274518SGustavo F. Padovan int __init l2cap_init(void)
47970a708f8fSGustavo F. Padovan {
47980a708f8fSGustavo F. Padovan 	int err;
47990a708f8fSGustavo F. Padovan 
4800bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
48010a708f8fSGustavo F. Padovan 	if (err < 0)
48020a708f8fSGustavo F. Padovan 		return err;
48030a708f8fSGustavo F. Padovan 
48040a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
48050a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
48060a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
48070a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
48080a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
48090a708f8fSGustavo F. Padovan 	}
48100a708f8fSGustavo F. Padovan 
48110a708f8fSGustavo F. Padovan 	return 0;
48120a708f8fSGustavo F. Padovan }
48130a708f8fSGustavo F. Padovan 
481464274518SGustavo F. Padovan void l2cap_exit(void)
48150a708f8fSGustavo F. Padovan {
48160a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
4817bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
48180a708f8fSGustavo F. Padovan }
48190a708f8fSGustavo F. Padovan 
48200a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
48210a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
4822