xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 63838725)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
7422e925bSMat Martineau    Copyright (c) 2012 Code Aurora Forum.  All rights reserved.
80a708f8fSGustavo F. Padovan 
90a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
100a708f8fSGustavo F. Padovan 
110a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
120a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
130a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
140a708f8fSGustavo F. Padovan 
150a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
160a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
180a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
190a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
200a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
210a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
220a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
230a708f8fSGustavo F. Padovan 
240a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
250a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
260a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
270a708f8fSGustavo F. Padovan */
280a708f8fSGustavo F. Padovan 
29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
300a708f8fSGustavo F. Padovan 
310a708f8fSGustavo F. Padovan #include <linux/module.h>
320a708f8fSGustavo F. Padovan 
330a708f8fSGustavo F. Padovan #include <linux/types.h>
340a708f8fSGustavo F. Padovan #include <linux/capability.h>
350a708f8fSGustavo F. Padovan #include <linux/errno.h>
360a708f8fSGustavo F. Padovan #include <linux/kernel.h>
370a708f8fSGustavo F. Padovan #include <linux/sched.h>
380a708f8fSGustavo F. Padovan #include <linux/slab.h>
390a708f8fSGustavo F. Padovan #include <linux/poll.h>
400a708f8fSGustavo F. Padovan #include <linux/fcntl.h>
410a708f8fSGustavo F. Padovan #include <linux/init.h>
420a708f8fSGustavo F. Padovan #include <linux/interrupt.h>
430a708f8fSGustavo F. Padovan #include <linux/socket.h>
440a708f8fSGustavo F. Padovan #include <linux/skbuff.h>
450a708f8fSGustavo F. Padovan #include <linux/list.h>
460a708f8fSGustavo F. Padovan #include <linux/device.h>
470a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
480a708f8fSGustavo F. Padovan #include <linux/seq_file.h>
490a708f8fSGustavo F. Padovan #include <linux/uaccess.h>
500a708f8fSGustavo F. Padovan #include <linux/crc16.h>
510a708f8fSGustavo F. Padovan #include <net/sock.h>
520a708f8fSGustavo F. Padovan 
530a708f8fSGustavo F. Padovan #include <asm/unaligned.h>
540a708f8fSGustavo F. Padovan 
550a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
560a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
570a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
58b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
590a708f8fSGustavo F. Padovan 
60b191e031SMat Martineau bool disable_ertm = 1;
610a708f8fSGustavo F. Padovan 
620a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
6350a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
640a708f8fSGustavo F. Padovan 
65b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
66b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
670a708f8fSGustavo F. Padovan 
680a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
690a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
704519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
714519de9aSGustavo F. Padovan 								void *data);
72710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
734519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
744519de9aSGustavo F. Padovan 				   struct l2cap_chan *chan, int err);
750a708f8fSGustavo F. Padovan 
76608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
77608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event);
78608bcc6dSMat Martineau 
790a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8071ba0e56SGustavo F. Padovan 
81baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
820a708f8fSGustavo F. Padovan {
833df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
84baa7e1faSGustavo F. Padovan 
853df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
863df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
873df91ea2SAndrei Emeltchenko 			return c;
880a708f8fSGustavo F. Padovan 	}
893df91ea2SAndrei Emeltchenko 	return NULL;
90baa7e1faSGustavo F. Padovan }
910a708f8fSGustavo F. Padovan 
92baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
930a708f8fSGustavo F. Padovan {
943df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
95baa7e1faSGustavo F. Padovan 
963df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
973df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
983df91ea2SAndrei Emeltchenko 			return c;
990a708f8fSGustavo F. Padovan 	}
1003df91ea2SAndrei Emeltchenko 	return NULL;
101baa7e1faSGustavo F. Padovan }
1020a708f8fSGustavo F. Padovan 
1030a708f8fSGustavo F. Padovan /* Find channel with given SCID.
104ef191adeSMat Martineau  * Returns locked channel. */
105baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1060a708f8fSGustavo F. Padovan {
10748454079SGustavo F. Padovan 	struct l2cap_chan *c;
108baa7e1faSGustavo F. Padovan 
1093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
110baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
111ef191adeSMat Martineau 	if (c)
112ef191adeSMat Martineau 		l2cap_chan_lock(c);
1133df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1143df91ea2SAndrei Emeltchenko 
11548454079SGustavo F. Padovan 	return c;
1160a708f8fSGustavo F. Padovan }
1170a708f8fSGustavo F. Padovan 
118baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1190a708f8fSGustavo F. Padovan {
1203df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
121baa7e1faSGustavo F. Padovan 
1223df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1233df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1243df91ea2SAndrei Emeltchenko 			return c;
1250a708f8fSGustavo F. Padovan 	}
1263df91ea2SAndrei Emeltchenko 	return NULL;
127baa7e1faSGustavo F. Padovan }
1280a708f8fSGustavo F. Padovan 
12923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1309e4425ffSGustavo F. Padovan {
13123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1329e4425ffSGustavo F. Padovan 
13323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
13423691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
13523691d75SGustavo F. Padovan 			return c;
1369e4425ffSGustavo F. Padovan 	}
137250938cbSSzymon Janc 	return NULL;
138250938cbSSzymon Janc }
1399e4425ffSGustavo F. Padovan 
1409e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1419e4425ffSGustavo F. Padovan {
14273b2ec18SGustavo F. Padovan 	int err;
14373b2ec18SGustavo F. Padovan 
144333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1459e4425ffSGustavo F. Padovan 
14623691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
14773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
14873b2ec18SGustavo F. Padovan 		goto done;
1499e4425ffSGustavo F. Padovan 	}
1509e4425ffSGustavo F. Padovan 
15173b2ec18SGustavo F. Padovan 	if (psm) {
1529e4425ffSGustavo F. Padovan 		chan->psm = psm;
1539e4425ffSGustavo F. Padovan 		chan->sport = psm;
15473b2ec18SGustavo F. Padovan 		err = 0;
15573b2ec18SGustavo F. Padovan 	} else {
15673b2ec18SGustavo F. Padovan 		u16 p;
1579e4425ffSGustavo F. Padovan 
15873b2ec18SGustavo F. Padovan 		err = -EINVAL;
15973b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
16023691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
16173b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
16273b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
16373b2ec18SGustavo F. Padovan 				err = 0;
16473b2ec18SGustavo F. Padovan 				break;
16573b2ec18SGustavo F. Padovan 			}
16673b2ec18SGustavo F. Padovan 	}
16773b2ec18SGustavo F. Padovan 
16873b2ec18SGustavo F. Padovan done:
169333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
17073b2ec18SGustavo F. Padovan 	return err;
1719e4425ffSGustavo F. Padovan }
1729e4425ffSGustavo F. Padovan 
1739e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1749e4425ffSGustavo F. Padovan {
175333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1769e4425ffSGustavo F. Padovan 
1779e4425ffSGustavo F. Padovan 	chan->scid = scid;
1789e4425ffSGustavo F. Padovan 
179333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1809e4425ffSGustavo F. Padovan 
1819e4425ffSGustavo F. Padovan 	return 0;
1829e4425ffSGustavo F. Padovan }
1839e4425ffSGustavo F. Padovan 
184baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1850a708f8fSGustavo F. Padovan {
1860a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1870a708f8fSGustavo F. Padovan 
1880a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
189baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1900a708f8fSGustavo F. Padovan 			return cid;
1910a708f8fSGustavo F. Padovan 	}
1920a708f8fSGustavo F. Padovan 
1930a708f8fSGustavo F. Padovan 	return 0;
1940a708f8fSGustavo F. Padovan }
1950a708f8fSGustavo F. Padovan 
1960e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
19789bc500eSGustavo F. Padovan {
19842d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
199badaaa00SGustavo F. Padovan 						state_to_string(state));
200badaaa00SGustavo F. Padovan 
20189bc500eSGustavo F. Padovan 	chan->state = state;
20289bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
20389bc500eSGustavo F. Padovan }
20489bc500eSGustavo F. Padovan 
2050e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2060e587be7SAndrei Emeltchenko {
2070e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2080e587be7SAndrei Emeltchenko 
2090e587be7SAndrei Emeltchenko 	lock_sock(sk);
2100e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2110e587be7SAndrei Emeltchenko 	release_sock(sk);
2120e587be7SAndrei Emeltchenko }
2130e587be7SAndrei Emeltchenko 
2142e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2152e0052e4SAndrei Emeltchenko {
2162e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2172e0052e4SAndrei Emeltchenko 
2182e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2192e0052e4SAndrei Emeltchenko }
2202e0052e4SAndrei Emeltchenko 
2212e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2222e0052e4SAndrei Emeltchenko {
2232e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2242e0052e4SAndrei Emeltchenko 
2252e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2262e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2272e0052e4SAndrei Emeltchenko 	release_sock(sk);
2282e0052e4SAndrei Emeltchenko }
2292e0052e4SAndrei Emeltchenko 
230608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
231608bcc6dSMat Martineau 					       u16 seq)
232608bcc6dSMat Martineau {
233608bcc6dSMat Martineau 	struct sk_buff *skb;
234608bcc6dSMat Martineau 
235608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
236608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
237608bcc6dSMat Martineau 			return skb;
238608bcc6dSMat Martineau 	}
239608bcc6dSMat Martineau 
240608bcc6dSMat Martineau 	return NULL;
241608bcc6dSMat Martineau }
242608bcc6dSMat Martineau 
2433c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2443c588192SMat Martineau 
2453c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2463c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2473c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2483c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2493c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2503c588192SMat Martineau  * and removed from the head in constant time, without further memory
2513c588192SMat Martineau  * allocs or frees.
2523c588192SMat Martineau  */
2533c588192SMat Martineau 
2543c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2553c588192SMat Martineau {
2563c588192SMat Martineau 	size_t alloc_size, i;
2573c588192SMat Martineau 
2583c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2593c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2603c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2613c588192SMat Martineau 	 */
2623c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2633c588192SMat Martineau 
2643c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2653c588192SMat Martineau 	if (!seq_list->list)
2663c588192SMat Martineau 		return -ENOMEM;
2673c588192SMat Martineau 
2683c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2693c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2703c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2713c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2723c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2733c588192SMat Martineau 
2743c588192SMat Martineau 	return 0;
2753c588192SMat Martineau }
2763c588192SMat Martineau 
2773c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2783c588192SMat Martineau {
2793c588192SMat Martineau 	kfree(seq_list->list);
2803c588192SMat Martineau }
2813c588192SMat Martineau 
2823c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2833c588192SMat Martineau 					   u16 seq)
2843c588192SMat Martineau {
2853c588192SMat Martineau 	/* Constant-time check for list membership */
2863c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2873c588192SMat Martineau }
2883c588192SMat Martineau 
2893c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2903c588192SMat Martineau {
2913c588192SMat Martineau 	u16 mask = seq_list->mask;
2923c588192SMat Martineau 
2933c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2943c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2953c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2963c588192SMat Martineau 	} else if (seq_list->head == seq) {
2973c588192SMat Martineau 		/* Head can be removed in constant time */
2983c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2993c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3003c588192SMat Martineau 
3013c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3023c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3033c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3043c588192SMat Martineau 		}
3053c588192SMat Martineau 	} else {
3063c588192SMat Martineau 		/* Walk the list to find the sequence number */
3073c588192SMat Martineau 		u16 prev = seq_list->head;
3083c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3093c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3103c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3113c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3123c588192SMat Martineau 		}
3133c588192SMat Martineau 
3143c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3153c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3163c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3173c588192SMat Martineau 		if (seq_list->tail == seq)
3183c588192SMat Martineau 			seq_list->tail = prev;
3193c588192SMat Martineau 	}
3203c588192SMat Martineau 	return seq;
3213c588192SMat Martineau }
3223c588192SMat Martineau 
3233c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3243c588192SMat Martineau {
3253c588192SMat Martineau 	/* Remove the head in constant time */
3263c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3273c588192SMat Martineau }
3283c588192SMat Martineau 
3293c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3303c588192SMat Martineau {
3313c588192SMat Martineau 	u16 i;
332f522ae36SGustavo Padovan 
333f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
334f522ae36SGustavo Padovan 		return;
335f522ae36SGustavo Padovan 
3363c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3373c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau 
3393c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3413c588192SMat Martineau }
3423c588192SMat Martineau 
3433c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3443c588192SMat Martineau {
3453c588192SMat Martineau 	u16 mask = seq_list->mask;
3463c588192SMat Martineau 
3473c588192SMat Martineau 	/* All appends happen in constant time */
3483c588192SMat Martineau 
349f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
350f522ae36SGustavo Padovan 		return;
351f522ae36SGustavo Padovan 
3523c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3533c588192SMat Martineau 		seq_list->head = seq;
3543c588192SMat Martineau 	else
3553c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3563c588192SMat Martineau 
3573c588192SMat Martineau 	seq_list->tail = seq;
3583c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3593c588192SMat Martineau }
3603c588192SMat Martineau 
361721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
362ab07801dSGustavo F. Padovan {
363721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
364721c4181SGustavo F. Padovan 							chan_timer.work);
3653df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
366ab07801dSGustavo F. Padovan 	int reason;
367ab07801dSGustavo F. Padovan 
368e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
369ab07801dSGustavo F. Padovan 
3703df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3716be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
372ab07801dSGustavo F. Padovan 
37389bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
374ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
37589bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
376ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
377ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
378ab07801dSGustavo F. Padovan 	else
379ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
380ab07801dSGustavo F. Padovan 
3810f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
382ab07801dSGustavo F. Padovan 
3836be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
384ab07801dSGustavo F. Padovan 
385ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3863df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3873df91ea2SAndrei Emeltchenko 
388371fd835SUlisses Furquim 	l2cap_chan_put(chan);
389ab07801dSGustavo F. Padovan }
390ab07801dSGustavo F. Padovan 
391eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3920a708f8fSGustavo F. Padovan {
39348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3940a708f8fSGustavo F. Padovan 
39548454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
39648454079SGustavo F. Padovan 	if (!chan)
39748454079SGustavo F. Padovan 		return NULL;
3980a708f8fSGustavo F. Padovan 
399c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
400c03b355eSAndrei Emeltchenko 
401333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40223691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
403333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40423691d75SGustavo F. Padovan 
405721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
406ab07801dSGustavo F. Padovan 
40789bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
40889bc500eSGustavo F. Padovan 
40971ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
41071ba0e56SGustavo F. Padovan 
4112827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4122827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4132827011fSMat Martineau 
414eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
415abc545b8SSzymon Janc 
41648454079SGustavo F. Padovan 	return chan;
4170a708f8fSGustavo F. Padovan }
4180a708f8fSGustavo F. Padovan 
41923691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4206ff5abbfSGustavo F. Padovan {
421333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
42223691d75SGustavo F. Padovan 	list_del(&chan->global_l);
423333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
42423691d75SGustavo F. Padovan 
425371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4266ff5abbfSGustavo F. Padovan }
4276ff5abbfSGustavo F. Padovan 
428bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
429bd4b1653SAndrei Emeltchenko {
430bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
431bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
432bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
433bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
434bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
435bd4b1653SAndrei Emeltchenko 
436bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
437bd4b1653SAndrei Emeltchenko }
438bd4b1653SAndrei Emeltchenko 
43914a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4400a708f8fSGustavo F. Padovan {
4410a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
442097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4430a708f8fSGustavo F. Padovan 
4449f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4450a708f8fSGustavo F. Padovan 
4468c1d787bSGustavo F. Padovan 	chan->conn = conn;
4470a708f8fSGustavo F. Padovan 
4485491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4495491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
450b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
451b62f328bSVille Tervo 			/* LE connection */
4520c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
453fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
454fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
455b62f328bSVille Tervo 		} else {
4560a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
457fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4580c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
459b62f328bSVille Tervo 		}
4605491120eSAndrei Emeltchenko 		break;
4615491120eSAndrei Emeltchenko 
4625491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4630a708f8fSGustavo F. Padovan 		/* Connectionless socket */
464fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
465fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4660c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4675491120eSAndrei Emeltchenko 		break;
4685491120eSAndrei Emeltchenko 
4695491120eSAndrei Emeltchenko 	default:
4700a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
471fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
472fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4730c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4740a708f8fSGustavo F. Padovan 	}
4750a708f8fSGustavo F. Padovan 
4768f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4778f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4788f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4798f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4808f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4818f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4828f7975b1SAndrei Emeltchenko 
483371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
484baa7e1faSGustavo F. Padovan 
4853df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
486643162a8SAndrei Emeltchenko }
487643162a8SAndrei Emeltchenko 
48814a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
489643162a8SAndrei Emeltchenko {
490643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
491643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4923df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4930a708f8fSGustavo F. Padovan }
4940a708f8fSGustavo F. Padovan 
4954519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4960a708f8fSGustavo F. Padovan {
49748454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4988c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4990a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
5000a708f8fSGustavo F. Padovan 
501c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5020a708f8fSGustavo F. Padovan 
50349208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5040a708f8fSGustavo F. Padovan 
5050a708f8fSGustavo F. Padovan 	if (conn) {
506baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5073df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5083d57dc68SGustavo F. Padovan 
509371fd835SUlisses Furquim 		l2cap_chan_put(chan);
510baa7e1faSGustavo F. Padovan 
5118c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5120a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
5130a708f8fSGustavo F. Padovan 	}
5140a708f8fSGustavo F. Padovan 
5156be36555SAndrei Emeltchenko 	lock_sock(sk);
5166be36555SAndrei Emeltchenko 
5170e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
5180a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
5190a708f8fSGustavo F. Padovan 
5200a708f8fSGustavo F. Padovan 	if (err)
5212e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5220a708f8fSGustavo F. Padovan 
5230a708f8fSGustavo F. Padovan 	if (parent) {
5240a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5250a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5260a708f8fSGustavo F. Padovan 	} else
5270a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5280a708f8fSGustavo F. Padovan 
5296be36555SAndrei Emeltchenko 	release_sock(sk);
5306be36555SAndrei Emeltchenko 
5312827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
5326ff5abbfSGustavo F. Padovan 		return;
5332ead70b8SGustavo F. Padovan 
53458d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5350a708f8fSGustavo F. Padovan 
5360c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5371a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5381a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5391a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5400a708f8fSGustavo F. Padovan 
541f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5420a708f8fSGustavo F. Padovan 
5433c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5443c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
5450a708f8fSGustavo F. Padovan 	}
5460a708f8fSGustavo F. Padovan }
5470a708f8fSGustavo F. Padovan 
5484519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5494519de9aSGustavo F. Padovan {
5504519de9aSGustavo F. Padovan 	struct sock *sk;
5514519de9aSGustavo F. Padovan 
5524519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5534519de9aSGustavo F. Padovan 
5544519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5550f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
556ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5573df91ea2SAndrei Emeltchenko 
5586be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
559c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
560ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5616be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5623df91ea2SAndrei Emeltchenko 
563ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5640f852724SGustavo F. Padovan 	}
5654519de9aSGustavo F. Padovan }
5664519de9aSGustavo F. Padovan 
5670f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5684519de9aSGustavo F. Padovan {
5694519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5704519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5714519de9aSGustavo F. Padovan 
572e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
573e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5744519de9aSGustavo F. Padovan 
57589bc500eSGustavo F. Padovan 	switch (chan->state) {
5764519de9aSGustavo F. Padovan 	case BT_LISTEN:
5776be36555SAndrei Emeltchenko 		lock_sock(sk);
5784519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
57989bc500eSGustavo F. Padovan 
5800e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
58189bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5826be36555SAndrei Emeltchenko 		release_sock(sk);
5834519de9aSGustavo F. Padovan 		break;
5844519de9aSGustavo F. Padovan 
5854519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5864519de9aSGustavo F. Padovan 	case BT_CONFIG:
587715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5884519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
589c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5904519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5914519de9aSGustavo F. Padovan 		} else
5924519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5934519de9aSGustavo F. Padovan 		break;
5944519de9aSGustavo F. Padovan 
5954519de9aSGustavo F. Padovan 	case BT_CONNECT2:
596715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5974519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5984519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5994519de9aSGustavo F. Padovan 			__u16 result;
6004519de9aSGustavo F. Padovan 
601c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
6024519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
6034519de9aSGustavo F. Padovan 			else
6044519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
60589bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
6064519de9aSGustavo F. Padovan 
6074519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6084519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6094519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
6104519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
6114519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6124519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6134519de9aSGustavo F. Padovan 		}
6144519de9aSGustavo F. Padovan 
6154519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6164519de9aSGustavo F. Padovan 		break;
6174519de9aSGustavo F. Padovan 
6184519de9aSGustavo F. Padovan 	case BT_CONNECT:
6194519de9aSGustavo F. Padovan 	case BT_DISCONN:
6204519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6214519de9aSGustavo F. Padovan 		break;
6224519de9aSGustavo F. Padovan 
6234519de9aSGustavo F. Padovan 	default:
6246be36555SAndrei Emeltchenko 		lock_sock(sk);
6254519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6266be36555SAndrei Emeltchenko 		release_sock(sk);
6274519de9aSGustavo F. Padovan 		break;
6284519de9aSGustavo F. Padovan 	}
6294519de9aSGustavo F. Padovan }
6304519de9aSGustavo F. Padovan 
6314343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6320a708f8fSGustavo F. Padovan {
633715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6344343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6350a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6360a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6370a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6380a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6390a708f8fSGustavo F. Padovan 		default:
6400a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6410a708f8fSGustavo F. Padovan 		}
642fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6434343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6444343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6450a708f8fSGustavo F. Padovan 
6464343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6470a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6480a708f8fSGustavo F. Padovan 		else
6490a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6500a708f8fSGustavo F. Padovan 	} else {
6514343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6520a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6530a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6540a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6550a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6560a708f8fSGustavo F. Padovan 		default:
6570a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6580a708f8fSGustavo F. Padovan 		}
6590a708f8fSGustavo F. Padovan 	}
6600a708f8fSGustavo F. Padovan }
6610a708f8fSGustavo F. Padovan 
6620a708f8fSGustavo F. Padovan /* Service level security */
663d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6640a708f8fSGustavo F. Padovan {
6658c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6660a708f8fSGustavo F. Padovan 	__u8 auth_type;
6670a708f8fSGustavo F. Padovan 
6684343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6690a708f8fSGustavo F. Padovan 
6704343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6710a708f8fSGustavo F. Padovan }
6720a708f8fSGustavo F. Padovan 
673b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6740a708f8fSGustavo F. Padovan {
6750a708f8fSGustavo F. Padovan 	u8 id;
6760a708f8fSGustavo F. Padovan 
6770a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6780a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6790a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6800a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6810a708f8fSGustavo F. Padovan 	 */
6820a708f8fSGustavo F. Padovan 
683333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6840a708f8fSGustavo F. Padovan 
6850a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6860a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6870a708f8fSGustavo F. Padovan 
6880a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6890a708f8fSGustavo F. Padovan 
690333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6910a708f8fSGustavo F. Padovan 
6920a708f8fSGustavo F. Padovan 	return id;
6930a708f8fSGustavo F. Padovan }
6940a708f8fSGustavo F. Padovan 
6954519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6960a708f8fSGustavo F. Padovan {
6970a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6980a708f8fSGustavo F. Padovan 	u8 flags;
6990a708f8fSGustavo F. Padovan 
7000a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
7010a708f8fSGustavo F. Padovan 
7020a708f8fSGustavo F. Padovan 	if (!skb)
7030a708f8fSGustavo F. Padovan 		return;
7040a708f8fSGustavo F. Padovan 
7050a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
7060a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
7070a708f8fSGustavo F. Padovan 	else
7080a708f8fSGustavo F. Padovan 		flags = ACL_START;
7090a708f8fSGustavo F. Padovan 
71014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7115e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
71214b12d0bSJaikumar Ganesh 
71373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7140a708f8fSGustavo F. Padovan }
7150a708f8fSGustavo F. Padovan 
71673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
71773d80debSLuiz Augusto von Dentz {
71873d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
71973d80debSLuiz Augusto von Dentz 	u16 flags;
72073d80debSLuiz Augusto von Dentz 
72173d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
72273d80debSLuiz Augusto von Dentz 							skb->priority);
72373d80debSLuiz Augusto von Dentz 
72473d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
72573d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
72673d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
72773d80debSLuiz Augusto von Dentz 	else
72873d80debSLuiz Augusto von Dentz 		flags = ACL_START;
72973d80debSLuiz Augusto von Dentz 
73073d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
73173d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7320a708f8fSGustavo F. Padovan }
7330a708f8fSGustavo F. Padovan 
734b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
735b5c6aaedSMat Martineau {
736b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
737b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
738b5c6aaedSMat Martineau 
739b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
740b5c6aaedSMat Martineau 		/* S-Frame */
741b5c6aaedSMat Martineau 		control->sframe = 1;
742b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
743b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
744b5c6aaedSMat Martineau 
745b5c6aaedSMat Martineau 		control->sar = 0;
746b5c6aaedSMat Martineau 		control->txseq = 0;
747b5c6aaedSMat Martineau 	} else {
748b5c6aaedSMat Martineau 		/* I-Frame */
749b5c6aaedSMat Martineau 		control->sframe = 0;
750b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
751b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
752b5c6aaedSMat Martineau 
753b5c6aaedSMat Martineau 		control->poll = 0;
754b5c6aaedSMat Martineau 		control->super = 0;
755b5c6aaedSMat Martineau 	}
756b5c6aaedSMat Martineau }
757b5c6aaedSMat Martineau 
758b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
759b5c6aaedSMat Martineau {
760b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
761b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
762b5c6aaedSMat Martineau 
763b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
764b5c6aaedSMat Martineau 		/* S-Frame */
765b5c6aaedSMat Martineau 		control->sframe = 1;
766b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
767b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
768b5c6aaedSMat Martineau 
769b5c6aaedSMat Martineau 		control->sar = 0;
770b5c6aaedSMat Martineau 		control->txseq = 0;
771b5c6aaedSMat Martineau 	} else {
772b5c6aaedSMat Martineau 		/* I-Frame */
773b5c6aaedSMat Martineau 		control->sframe = 0;
774b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
775b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
776b5c6aaedSMat Martineau 
777b5c6aaedSMat Martineau 		control->poll = 0;
778b5c6aaedSMat Martineau 		control->super = 0;
779b5c6aaedSMat Martineau 	}
780b5c6aaedSMat Martineau }
781b5c6aaedSMat Martineau 
782b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
783b5c6aaedSMat Martineau 				    struct sk_buff *skb)
784b5c6aaedSMat Martineau {
785b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
786b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
787b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
788cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
789b5c6aaedSMat Martineau 	} else {
790b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
791b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
792cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
793b5c6aaedSMat Martineau 	}
794b5c6aaedSMat Martineau }
795b5c6aaedSMat Martineau 
796b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
797b5c6aaedSMat Martineau {
798b5c6aaedSMat Martineau 	u32 packed;
799b5c6aaedSMat Martineau 
800b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
801b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
802b5c6aaedSMat Martineau 
803b5c6aaedSMat Martineau 	if (control->sframe) {
804b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
805b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
806b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
807b5c6aaedSMat Martineau 	} else {
808b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
809b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
810b5c6aaedSMat Martineau 	}
811b5c6aaedSMat Martineau 
812b5c6aaedSMat Martineau 	return packed;
813b5c6aaedSMat Martineau }
814b5c6aaedSMat Martineau 
815b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
816b5c6aaedSMat Martineau {
817b5c6aaedSMat Martineau 	u16 packed;
818b5c6aaedSMat Martineau 
819b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
820b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
821b5c6aaedSMat Martineau 
822b5c6aaedSMat Martineau 	if (control->sframe) {
823b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
824b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
825b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
826b5c6aaedSMat Martineau 	} else {
827b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
828b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
829b5c6aaedSMat Martineau 	}
830b5c6aaedSMat Martineau 
831b5c6aaedSMat Martineau 	return packed;
832b5c6aaedSMat Martineau }
833b5c6aaedSMat Martineau 
834b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
835b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
836b5c6aaedSMat Martineau 				  struct sk_buff *skb)
837b5c6aaedSMat Martineau {
838b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
839b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
840b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
841b5c6aaedSMat Martineau 	} else {
842b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
843b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
844b5c6aaedSMat Martineau 	}
845b5c6aaedSMat Martineau }
846b5c6aaedSMat Martineau 
847a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
848a67d7f6fSMat Martineau 					       u32 control)
8490a708f8fSGustavo F. Padovan {
8500a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8510a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
852a67d7f6fSMat Martineau 	int hlen;
8530a708f8fSGustavo F. Padovan 
854e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
855e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
856e4ca6d98SAndrei Emeltchenko 	else
857e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8580a708f8fSGustavo F. Padovan 
8590a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
86003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8610a708f8fSGustavo F. Padovan 
862a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
8630a708f8fSGustavo F. Padovan 
8640a708f8fSGustavo F. Padovan 	if (!skb)
865a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
8660a708f8fSGustavo F. Padovan 
8670a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8680a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
869fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
87088843ab0SAndrei Emeltchenko 
871a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
872a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
873a67d7f6fSMat Martineau 	else
874a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
8750a708f8fSGustavo F. Padovan 
87647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
877a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
87803a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8790a708f8fSGustavo F. Padovan 	}
8800a708f8fSGustavo F. Padovan 
88173d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
882a67d7f6fSMat Martineau 	return skb;
883a67d7f6fSMat Martineau }
884a67d7f6fSMat Martineau 
885a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
886a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
887a67d7f6fSMat Martineau {
888a67d7f6fSMat Martineau 	struct sk_buff *skb;
889a67d7f6fSMat Martineau 	u32 control_field;
890a67d7f6fSMat Martineau 
891a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
892a67d7f6fSMat Martineau 
893a67d7f6fSMat Martineau 	if (!control->sframe)
894a67d7f6fSMat Martineau 		return;
895a67d7f6fSMat Martineau 
896a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
897a67d7f6fSMat Martineau 	    !control->poll)
898a67d7f6fSMat Martineau 		control->final = 1;
899a67d7f6fSMat Martineau 
900a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
901a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
902a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
903a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
904a67d7f6fSMat Martineau 
905a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
906a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
907a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
908a67d7f6fSMat Martineau 	}
909a67d7f6fSMat Martineau 
910a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
911a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
912a67d7f6fSMat Martineau 
913a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
914a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
915a67d7f6fSMat Martineau 	else
916a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
917a67d7f6fSMat Martineau 
918a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
919a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
92073d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
9210a708f8fSGustavo F. Padovan }
9220a708f8fSGustavo F. Padovan 
92388843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
9240a708f8fSGustavo F. Padovan {
925e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
926ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
927e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
9280a708f8fSGustavo F. Padovan 	} else
929ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
9300a708f8fSGustavo F. Padovan 
9310b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
9320a708f8fSGustavo F. Padovan }
9330a708f8fSGustavo F. Padovan 
934b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9350a708f8fSGustavo F. Padovan {
936c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9370a708f8fSGustavo F. Padovan }
9380a708f8fSGustavo F. Padovan 
9399b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9409b27f350SAndrei Emeltchenko {
9419b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9429b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9439b27f350SAndrei Emeltchenko 
9449b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9459b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9469b27f350SAndrei Emeltchenko 
9479b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9489b27f350SAndrei Emeltchenko 
9499b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9509b27f350SAndrei Emeltchenko 
9519b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9529b27f350SAndrei Emeltchenko }
9539b27f350SAndrei Emeltchenko 
9549f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9559f0caeb1SVinicius Costa Gomes {
9569f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9579f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9589f0caeb1SVinicius Costa Gomes 
9599f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9609f0caeb1SVinicius Costa Gomes 
9619f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9629f0caeb1SVinicius Costa Gomes 
9639f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9649f0caeb1SVinicius Costa Gomes 
9652827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9669f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9679f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9689f0caeb1SVinicius Costa Gomes 
9699f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9709f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9719f0caeb1SVinicius Costa Gomes 
9729f0caeb1SVinicius Costa Gomes 	if (parent)
9739f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9749f0caeb1SVinicius Costa Gomes 
9759f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9769f0caeb1SVinicius Costa Gomes }
9779f0caeb1SVinicius Costa Gomes 
978fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9790a708f8fSGustavo F. Padovan {
9808c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9810a708f8fSGustavo F. Padovan 
9829f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9839f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9849f0caeb1SVinicius Costa Gomes 		return;
9859f0caeb1SVinicius Costa Gomes 	}
9869f0caeb1SVinicius Costa Gomes 
9870a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9880a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9890a708f8fSGustavo F. Padovan 			return;
9900a708f8fSGustavo F. Padovan 
991d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9929b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9939b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9940a708f8fSGustavo F. Padovan 	} else {
9950a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9960a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9970a708f8fSGustavo F. Padovan 
9980a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9990a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
10000a708f8fSGustavo F. Padovan 
1001ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
10020a708f8fSGustavo F. Padovan 
10030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
10040a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
10050a708f8fSGustavo F. Padovan 	}
10060a708f8fSGustavo F. Padovan }
10070a708f8fSGustavo F. Padovan 
10080a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
10090a708f8fSGustavo F. Padovan {
10100a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
10110a708f8fSGustavo F. Padovan 	if (!disable_ertm)
10120a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
10130a708f8fSGustavo F. Padovan 
10140a708f8fSGustavo F. Padovan 	switch (mode) {
10150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
10160a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
10170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
10180a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
10190a708f8fSGustavo F. Padovan 	default:
10200a708f8fSGustavo F. Padovan 		return 0x00;
10210a708f8fSGustavo F. Padovan 	}
10220a708f8fSGustavo F. Padovan }
10230a708f8fSGustavo F. Padovan 
10244519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
10250a708f8fSGustavo F. Padovan {
10266be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
10270a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
10280a708f8fSGustavo F. Padovan 
10290a708f8fSGustavo F. Padovan 	if (!conn)
10300a708f8fSGustavo F. Padovan 		return;
10310a708f8fSGustavo F. Padovan 
10320c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
10331a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
10341a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
10351a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
10360a708f8fSGustavo F. Padovan 	}
10370a708f8fSGustavo F. Padovan 
1038fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1039fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10400a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10410a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10420a708f8fSGustavo F. Padovan 
10436be36555SAndrei Emeltchenko 	lock_sock(sk);
10440e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10452e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10466be36555SAndrei Emeltchenko 	release_sock(sk);
10470a708f8fSGustavo F. Padovan }
10480a708f8fSGustavo F. Padovan 
10490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10510a708f8fSGustavo F. Padovan {
10523df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10530a708f8fSGustavo F. Padovan 
10540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10550a708f8fSGustavo F. Padovan 
10563df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10570a708f8fSGustavo F. Padovan 
10583df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
105948454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1060baa7e1faSGustavo F. Padovan 
10616be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10620a708f8fSGustavo F. Padovan 
1063715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10646be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10650a708f8fSGustavo F. Padovan 			continue;
10660a708f8fSGustavo F. Padovan 		}
10670a708f8fSGustavo F. Padovan 
106889bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1069d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1070b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10716be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10720a708f8fSGustavo F. Padovan 				continue;
10730a708f8fSGustavo F. Padovan 			}
10740a708f8fSGustavo F. Padovan 
1075c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1076c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1077c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10780f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10796be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10800a708f8fSGustavo F. Padovan 				continue;
10810a708f8fSGustavo F. Padovan 			}
10820a708f8fSGustavo F. Padovan 
10839b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10840a708f8fSGustavo F. Padovan 
108589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10860a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10870a708f8fSGustavo F. Padovan 			char buf[128];
1088fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1089fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10900a708f8fSGustavo F. Padovan 
1091d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10926be36555SAndrei Emeltchenko 				lock_sock(sk);
1093c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1094c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
10950a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10960a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10970a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
109805e9a2f6SIlia Kolomisnky 					if (parent)
10990a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
11000a708f8fSGustavo F. Padovan 
11010a708f8fSGustavo F. Padovan 				} else {
11020e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
11030a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
11040a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
11050a708f8fSGustavo F. Padovan 				}
11066be36555SAndrei Emeltchenko 				release_sock(sk);
11070a708f8fSGustavo F. Padovan 			} else {
11080a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11090a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
11100a708f8fSGustavo F. Padovan 			}
11110a708f8fSGustavo F. Padovan 
1112fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1113fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
11140a708f8fSGustavo F. Padovan 
1115c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
11160a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
11176be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
11180a708f8fSGustavo F. Padovan 				continue;
11190a708f8fSGustavo F. Padovan 			}
11200a708f8fSGustavo F. Padovan 
1121c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
11220a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
112373ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
112473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
11250a708f8fSGustavo F. Padovan 		}
11260a708f8fSGustavo F. Padovan 
11276be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
11280a708f8fSGustavo F. Padovan 	}
11290a708f8fSGustavo F. Padovan 
11303df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
11310a708f8fSGustavo F. Padovan }
11320a708f8fSGustavo F. Padovan 
1133c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1134b62f328bSVille Tervo  * Returns closest match, locked.
1135b62f328bSVille Tervo  */
1136d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1137c2287681SIdo Yariv 						    bdaddr_t *src,
1138c2287681SIdo Yariv 						    bdaddr_t *dst)
1139b62f328bSVille Tervo {
114023691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1141b62f328bSVille Tervo 
114223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1143b62f328bSVille Tervo 
114423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
114523691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1146fe4128e0SGustavo F. Padovan 
114789bc500eSGustavo F. Padovan 		if (state && c->state != state)
1148b62f328bSVille Tervo 			continue;
1149b62f328bSVille Tervo 
115023691d75SGustavo F. Padovan 		if (c->scid == cid) {
1151c2287681SIdo Yariv 			int src_match, dst_match;
1152c2287681SIdo Yariv 			int src_any, dst_any;
1153c2287681SIdo Yariv 
1154b62f328bSVille Tervo 			/* Exact match. */
1155c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1156c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1157c2287681SIdo Yariv 			if (src_match && dst_match) {
115823691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
115923691d75SGustavo F. Padovan 				return c;
116023691d75SGustavo F. Padovan 			}
1161b62f328bSVille Tervo 
1162b62f328bSVille Tervo 			/* Closest match */
1163c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1164c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1165c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1166c2287681SIdo Yariv 			    (src_any && dst_any))
116723691d75SGustavo F. Padovan 				c1 = c;
1168b62f328bSVille Tervo 		}
1169b62f328bSVille Tervo 	}
1170280f294fSGustavo F. Padovan 
117123691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1172b62f328bSVille Tervo 
117323691d75SGustavo F. Padovan 	return c1;
1174b62f328bSVille Tervo }
1175b62f328bSVille Tervo 
1176b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1177b62f328bSVille Tervo {
1178c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
117923691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1180b62f328bSVille Tervo 
1181b62f328bSVille Tervo 	BT_DBG("");
1182b62f328bSVille Tervo 
1183b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
118423691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1185c2287681SIdo Yariv 					  conn->src, conn->dst);
118623691d75SGustavo F. Padovan 	if (!pchan)
1187b62f328bSVille Tervo 		return;
1188b62f328bSVille Tervo 
118923691d75SGustavo F. Padovan 	parent = pchan->sk;
119023691d75SGustavo F. Padovan 
1191aa2ac881SGustavo F. Padovan 	lock_sock(parent);
119262f3a2cfSGustavo F. Padovan 
1193b62f328bSVille Tervo 	/* Check for backlog size */
1194b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1195b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1196b62f328bSVille Tervo 		goto clean;
1197b62f328bSVille Tervo 	}
1198b62f328bSVille Tervo 
119980808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
120080808e43SGustavo F. Padovan 	if (!chan)
1201b62f328bSVille Tervo 		goto clean;
1202b62f328bSVille Tervo 
120380808e43SGustavo F. Padovan 	sk = chan->sk;
12045d41ce1dSGustavo F. Padovan 
1205b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1206b62f328bSVille Tervo 
1207b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1208b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1209b62f328bSVille Tervo 
1210d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1211d1010240SGustavo F. Padovan 
12123d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
121348454079SGustavo F. Padovan 
1214c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1215b62f328bSVille Tervo 
12160e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1217b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1218b62f328bSVille Tervo 
1219b62f328bSVille Tervo clean:
1220aa2ac881SGustavo F. Padovan 	release_sock(parent);
1221b62f328bSVille Tervo }
1222b62f328bSVille Tervo 
12230a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
12240a708f8fSGustavo F. Padovan {
122548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12260a708f8fSGustavo F. Padovan 
12270a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12280a708f8fSGustavo F. Padovan 
1229b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1230b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1231b62f328bSVille Tervo 
1232160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1233160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1234160dc6acSVinicius Costa Gomes 
12353df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12360a708f8fSGustavo F. Padovan 
12373df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1238baa7e1faSGustavo F. Padovan 
12396be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12400a708f8fSGustavo F. Padovan 
124163128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1242b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1243cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1244acd7d370SVille Tervo 
124563128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12466be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1247c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12486be36555SAndrei Emeltchenko 			lock_sock(sk);
12490e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12500a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12516be36555SAndrei Emeltchenko 			release_sock(sk);
1252b501d6a1SAnderson Briglia 
125389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1254fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12550a708f8fSGustavo F. Padovan 
12566be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12570a708f8fSGustavo F. Padovan 	}
12580a708f8fSGustavo F. Padovan 
12593df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12600a708f8fSGustavo F. Padovan }
12610a708f8fSGustavo F. Padovan 
12620a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12630a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12640a708f8fSGustavo F. Padovan {
126548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12660a708f8fSGustavo F. Padovan 
12670a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12680a708f8fSGustavo F. Padovan 
12693df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12700a708f8fSGustavo F. Padovan 
12713df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1272ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12732e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12740a708f8fSGustavo F. Padovan 	}
12750a708f8fSGustavo F. Padovan 
12763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12770a708f8fSGustavo F. Padovan }
12780a708f8fSGustavo F. Padovan 
1279f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12800a708f8fSGustavo F. Padovan {
1281f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1282030013d8SGustavo F. Padovan 							info_timer.work);
12830a708f8fSGustavo F. Padovan 
12840a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12850a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12860a708f8fSGustavo F. Padovan 
12870a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12880a708f8fSGustavo F. Padovan }
12890a708f8fSGustavo F. Padovan 
12905d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12915d3de7dfSVinicius Costa Gomes {
12925d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12935d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12945d3de7dfSVinicius Costa Gomes 
12955d3de7dfSVinicius Costa Gomes 	if (!conn)
12965d3de7dfSVinicius Costa Gomes 		return;
12975d3de7dfSVinicius Costa Gomes 
12985d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12995d3de7dfSVinicius Costa Gomes 
13005d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
13015d3de7dfSVinicius Costa Gomes 
13023df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13033df91ea2SAndrei Emeltchenko 
13045d3de7dfSVinicius Costa Gomes 	/* Kill channels */
13055d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
130661d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
13076be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13086be36555SAndrei Emeltchenko 
13095d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
13106be36555SAndrei Emeltchenko 
13116be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13126be36555SAndrei Emeltchenko 
13135d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
131461d6ef3eSMat Martineau 		l2cap_chan_put(chan);
13155d3de7dfSVinicius Costa Gomes 	}
13165d3de7dfSVinicius Costa Gomes 
13173df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
13183df91ea2SAndrei Emeltchenko 
131973d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
132073d80debSLuiz Augusto von Dentz 
13215d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1322127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
13235d3de7dfSVinicius Costa Gomes 
132451a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1325127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
13268aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1327d26a2345SVinicius Costa Gomes 	}
13285d3de7dfSVinicius Costa Gomes 
13295d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
13305d3de7dfSVinicius Costa Gomes 	kfree(conn);
13315d3de7dfSVinicius Costa Gomes }
13325d3de7dfSVinicius Costa Gomes 
13336c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
13345d3de7dfSVinicius Costa Gomes {
13356c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
13366c9d42a1SGustavo F. Padovan 						security_timer.work);
13375d3de7dfSVinicius Costa Gomes 
13385d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
13395d3de7dfSVinicius Costa Gomes }
13405d3de7dfSVinicius Costa Gomes 
13410a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13420a708f8fSGustavo F. Padovan {
13430a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
134473d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13450a708f8fSGustavo F. Padovan 
13460a708f8fSGustavo F. Padovan 	if (conn || status)
13470a708f8fSGustavo F. Padovan 		return conn;
13480a708f8fSGustavo F. Padovan 
134973d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
135073d80debSLuiz Augusto von Dentz 	if (!hchan)
13510a708f8fSGustavo F. Padovan 		return NULL;
13520a708f8fSGustavo F. Padovan 
135373d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
135473d80debSLuiz Augusto von Dentz 	if (!conn) {
135573d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
135673d80debSLuiz Augusto von Dentz 		return NULL;
135773d80debSLuiz Augusto von Dentz 	}
135873d80debSLuiz Augusto von Dentz 
13590a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13600a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
136173d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13620a708f8fSGustavo F. Padovan 
136373d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13640a708f8fSGustavo F. Padovan 
1365acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1366acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1367acd7d370SVille Tervo 	else
13680a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1369acd7d370SVille Tervo 
13700a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13710a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13720a708f8fSGustavo F. Padovan 
13730a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13740a708f8fSGustavo F. Padovan 
13750a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13763df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1377baa7e1faSGustavo F. Padovan 
1378baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13790a708f8fSGustavo F. Padovan 
13805d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13816c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13825d3de7dfSVinicius Costa Gomes 	else
1383030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13840a708f8fSGustavo F. Padovan 
13859f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13860a708f8fSGustavo F. Padovan 
13870a708f8fSGustavo F. Padovan 	return conn;
13880a708f8fSGustavo F. Padovan }
13890a708f8fSGustavo F. Padovan 
13900a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13910a708f8fSGustavo F. Padovan 
1392c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13930a708f8fSGustavo F. Padovan  * Returns closest match.
13940a708f8fSGustavo F. Padovan  */
1395c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1396c2287681SIdo Yariv 						   bdaddr_t *src,
1397c2287681SIdo Yariv 						   bdaddr_t *dst)
13980a708f8fSGustavo F. Padovan {
139923691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
14000a708f8fSGustavo F. Padovan 
140123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
14020a708f8fSGustavo F. Padovan 
140323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
140423691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1405fe4128e0SGustavo F. Padovan 
140689bc500eSGustavo F. Padovan 		if (state && c->state != state)
14070a708f8fSGustavo F. Padovan 			continue;
14080a708f8fSGustavo F. Padovan 
140923691d75SGustavo F. Padovan 		if (c->psm == psm) {
1410c2287681SIdo Yariv 			int src_match, dst_match;
1411c2287681SIdo Yariv 			int src_any, dst_any;
1412c2287681SIdo Yariv 
14130a708f8fSGustavo F. Padovan 			/* Exact match. */
1414c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1415c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1416c2287681SIdo Yariv 			if (src_match && dst_match) {
1417a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
141823691d75SGustavo F. Padovan 				return c;
141923691d75SGustavo F. Padovan 			}
14200a708f8fSGustavo F. Padovan 
14210a708f8fSGustavo F. Padovan 			/* Closest match */
1422c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1423c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1424c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1425c2287681SIdo Yariv 			    (src_any && dst_any))
142623691d75SGustavo F. Padovan 				c1 = c;
14270a708f8fSGustavo F. Padovan 		}
14280a708f8fSGustavo F. Padovan 	}
14290a708f8fSGustavo F. Padovan 
143023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
14310a708f8fSGustavo F. Padovan 
143223691d75SGustavo F. Padovan 	return c1;
14330a708f8fSGustavo F. Padovan }
14340a708f8fSGustavo F. Padovan 
14358e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
14368e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14370a708f8fSGustavo F. Padovan {
14385d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14390a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14400a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14410a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14420a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14430a708f8fSGustavo F. Padovan 	__u8 auth_type;
14440a708f8fSGustavo F. Padovan 	int err;
14450a708f8fSGustavo F. Padovan 
14468e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14478e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14480a708f8fSGustavo F. Padovan 
14490a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14500a708f8fSGustavo F. Padovan 	if (!hdev)
14510a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14520a708f8fSGustavo F. Padovan 
145309fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14540a708f8fSGustavo F. Padovan 
14556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
145603a00194SGustavo F. Padovan 
145703a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
145803a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
145903a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
146003a00194SGustavo F. Padovan 		err = -EINVAL;
146103a00194SGustavo F. Padovan 		goto done;
146203a00194SGustavo F. Padovan 	}
146303a00194SGustavo F. Padovan 
146403a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
146503a00194SGustavo F. Padovan 		err = -EINVAL;
146603a00194SGustavo F. Padovan 		goto done;
146703a00194SGustavo F. Padovan 	}
146803a00194SGustavo F. Padovan 
146903a00194SGustavo F. Padovan 	switch (chan->mode) {
147003a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
147103a00194SGustavo F. Padovan 		break;
147203a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
147303a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
147403a00194SGustavo F. Padovan 		if (!disable_ertm)
147503a00194SGustavo F. Padovan 			break;
147603a00194SGustavo F. Padovan 		/* fall through */
147703a00194SGustavo F. Padovan 	default:
147803a00194SGustavo F. Padovan 		err = -ENOTSUPP;
147903a00194SGustavo F. Padovan 		goto done;
148003a00194SGustavo F. Padovan 	}
148103a00194SGustavo F. Padovan 
14826be36555SAndrei Emeltchenko 	lock_sock(sk);
14836be36555SAndrei Emeltchenko 
148403a00194SGustavo F. Padovan 	switch (sk->sk_state) {
148503a00194SGustavo F. Padovan 	case BT_CONNECT:
148603a00194SGustavo F. Padovan 	case BT_CONNECT2:
148703a00194SGustavo F. Padovan 	case BT_CONFIG:
148803a00194SGustavo F. Padovan 		/* Already connecting */
148903a00194SGustavo F. Padovan 		err = 0;
14906be36555SAndrei Emeltchenko 		release_sock(sk);
149103a00194SGustavo F. Padovan 		goto done;
149203a00194SGustavo F. Padovan 
149303a00194SGustavo F. Padovan 	case BT_CONNECTED:
149403a00194SGustavo F. Padovan 		/* Already connected */
149503a00194SGustavo F. Padovan 		err = -EISCONN;
14966be36555SAndrei Emeltchenko 		release_sock(sk);
149703a00194SGustavo F. Padovan 		goto done;
149803a00194SGustavo F. Padovan 
149903a00194SGustavo F. Padovan 	case BT_OPEN:
150003a00194SGustavo F. Padovan 	case BT_BOUND:
150103a00194SGustavo F. Padovan 		/* Can connect */
150203a00194SGustavo F. Padovan 		break;
150303a00194SGustavo F. Padovan 
150403a00194SGustavo F. Padovan 	default:
150503a00194SGustavo F. Padovan 		err = -EBADFD;
15066be36555SAndrei Emeltchenko 		release_sock(sk);
150703a00194SGustavo F. Padovan 		goto done;
150803a00194SGustavo F. Padovan 	}
150903a00194SGustavo F. Padovan 
151003a00194SGustavo F. Padovan 	/* Set destination address and psm */
15119219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
15126be36555SAndrei Emeltchenko 
15136be36555SAndrei Emeltchenko 	release_sock(sk);
15146be36555SAndrei Emeltchenko 
151503a00194SGustavo F. Padovan 	chan->psm = psm;
151603a00194SGustavo F. Padovan 	chan->dcid = cid;
15170a708f8fSGustavo F. Padovan 
15184343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
15190a708f8fSGustavo F. Padovan 
1520fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
15218e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
15224343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1523acd7d370SVille Tervo 	else
15248e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
15254343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1526acd7d370SVille Tervo 
152730e76272SVille Tervo 	if (IS_ERR(hcon)) {
152830e76272SVille Tervo 		err = PTR_ERR(hcon);
15290a708f8fSGustavo F. Padovan 		goto done;
153030e76272SVille Tervo 	}
15310a708f8fSGustavo F. Padovan 
15320a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
15330a708f8fSGustavo F. Padovan 	if (!conn) {
15340a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
153530e76272SVille Tervo 		err = -ENOMEM;
15360a708f8fSGustavo F. Padovan 		goto done;
15370a708f8fSGustavo F. Padovan 	}
15380a708f8fSGustavo F. Padovan 
15399f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15409f0caeb1SVinicius Costa Gomes 		err = 0;
15419f0caeb1SVinicius Costa Gomes 
15429f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15439f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15449f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15459f0caeb1SVinicius Costa Gomes 		}
15469f0caeb1SVinicius Costa Gomes 
15479f0caeb1SVinicius Costa Gomes 		if (err)
15489f0caeb1SVinicius Costa Gomes 			goto done;
15499f0caeb1SVinicius Costa Gomes 	}
15509f0caeb1SVinicius Costa Gomes 
15510a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15520a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15530a708f8fSGustavo F. Padovan 
15546be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
155548454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15566be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
155748454079SGustavo F. Padovan 
15586be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1559c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15600a708f8fSGustavo F. Padovan 
15610a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1562715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1563c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1564d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15656be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15660a708f8fSGustavo F. Padovan 		} else
1567fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15680a708f8fSGustavo F. Padovan 	}
15690a708f8fSGustavo F. Padovan 
157030e76272SVille Tervo 	err = 0;
157130e76272SVille Tervo 
15720a708f8fSGustavo F. Padovan done:
15736be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
157409fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15750a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15760a708f8fSGustavo F. Padovan 	return err;
15770a708f8fSGustavo F. Padovan }
15780a708f8fSGustavo F. Padovan 
1579dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15800a708f8fSGustavo F. Padovan {
15818c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15820a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15830a708f8fSGustavo F. Padovan 	int err = 0;
15840a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15850a708f8fSGustavo F. Padovan 
15860a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15870a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1588a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15890a708f8fSGustavo F. Padovan 		if (!timeo)
15900a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15910a708f8fSGustavo F. Padovan 
15920a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15930a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15940a708f8fSGustavo F. Padovan 			break;
15950a708f8fSGustavo F. Padovan 		}
15960a708f8fSGustavo F. Padovan 
15970a708f8fSGustavo F. Padovan 		release_sock(sk);
15980a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15990a708f8fSGustavo F. Padovan 		lock_sock(sk);
1600a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
16010a708f8fSGustavo F. Padovan 
16020a708f8fSGustavo F. Padovan 		err = sock_error(sk);
16030a708f8fSGustavo F. Padovan 		if (err)
16040a708f8fSGustavo F. Padovan 			break;
16050a708f8fSGustavo F. Padovan 	}
16060a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
16070a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
16080a708f8fSGustavo F. Padovan 	return err;
16090a708f8fSGustavo F. Padovan }
16100a708f8fSGustavo F. Padovan 
1611721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
16120a708f8fSGustavo F. Padovan {
1613721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1614721c4181SGustavo F. Padovan 							monitor_timer.work);
16150a708f8fSGustavo F. Padovan 
1616525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
16170a708f8fSGustavo F. Padovan 
16186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16196be36555SAndrei Emeltchenko 
16202c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
16218c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16226be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16238d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
16240a708f8fSGustavo F. Padovan 		return;
16250a708f8fSGustavo F. Padovan 	}
16260a708f8fSGustavo F. Padovan 
16276a026610SGustavo F. Padovan 	chan->retry_count++;
16281a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16290a708f8fSGustavo F. Padovan 
1630525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16316be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16328d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16330a708f8fSGustavo F. Padovan }
16340a708f8fSGustavo F. Padovan 
1635721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
16360a708f8fSGustavo F. Padovan {
1637721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1638721c4181SGustavo F. Padovan 							retrans_timer.work);
16390a708f8fSGustavo F. Padovan 
164049208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16410a708f8fSGustavo F. Padovan 
16426be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16436be36555SAndrei Emeltchenko 
16446a026610SGustavo F. Padovan 	chan->retry_count = 1;
16451a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16460a708f8fSGustavo F. Padovan 
1647e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16480a708f8fSGustavo F. Padovan 
1649525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16506be36555SAndrei Emeltchenko 
16516be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16528d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16530a708f8fSGustavo F. Padovan }
16540a708f8fSGustavo F. Padovan 
16553733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan,
16563733937dSMat Martineau 				struct sk_buff_head *skbs)
16570a708f8fSGustavo F. Padovan {
16580a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16593733937dSMat Martineau 	struct l2cap_ctrl *control;
16600a708f8fSGustavo F. Padovan 
16613733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
16623733937dSMat Martineau 
16633733937dSMat Martineau 	if (chan->state != BT_CONNECTED)
16643733937dSMat Martineau 		return -ENOTCONN;
16653733937dSMat Martineau 
16663733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
16673733937dSMat Martineau 
16683733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
16693733937dSMat Martineau 
16703733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
16713733937dSMat Martineau 
16723733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
16733733937dSMat Martineau 		control = &bt_cb(skb)->control;
16743733937dSMat Martineau 
16753733937dSMat Martineau 		control->reqseq = 0;
16763733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
16773733937dSMat Martineau 
16783733937dSMat Martineau 		__pack_control(chan, control, skb);
16790a708f8fSGustavo F. Padovan 
168047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
16813733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
16823733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
16830a708f8fSGustavo F. Padovan 		}
16840a708f8fSGustavo F. Padovan 
16854343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16860a708f8fSGustavo F. Padovan 
16873733937dSMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
16883733937dSMat Martineau 
1689836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16903733937dSMat Martineau 		chan->frames_sent++;
16910a708f8fSGustavo F. Padovan 	}
16923733937dSMat Martineau 
16933733937dSMat Martineau 	return 0;
16940a708f8fSGustavo F. Padovan }
16950a708f8fSGustavo F. Padovan 
169667c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
16970a708f8fSGustavo F. Padovan {
16980a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
169918a48e76SMat Martineau 	struct l2cap_ctrl *control;
170018a48e76SMat Martineau 	int sent = 0;
170118a48e76SMat Martineau 
170218a48e76SMat Martineau 	BT_DBG("chan %p", chan);
17030a708f8fSGustavo F. Padovan 
170489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17050a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17060a708f8fSGustavo F. Padovan 
170794122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
170894122bbeSMat Martineau 		return 0;
170994122bbeSMat Martineau 
171018a48e76SMat Martineau 	while (chan->tx_send_head &&
171118a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
171218a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
17130a708f8fSGustavo F. Padovan 
171418a48e76SMat Martineau 		skb = chan->tx_send_head;
17150a708f8fSGustavo F. Padovan 
171618a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
171718a48e76SMat Martineau 		control = &bt_cb(skb)->control;
17180a708f8fSGustavo F. Padovan 
1719e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
172018a48e76SMat Martineau 			control->final = 1;
1721e2ab4353SGustavo F. Padovan 
172218a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
172318a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
172418a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
17250a708f8fSGustavo F. Padovan 
172618a48e76SMat Martineau 		__pack_control(chan, control, skb);
17270a708f8fSGustavo F. Padovan 
172847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
172918a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
173018a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
17310a708f8fSGustavo F. Padovan 		}
17320a708f8fSGustavo F. Padovan 
173318a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
173418a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
173518a48e76SMat Martineau 		 */
173618a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
173718a48e76SMat Martineau 
173818a48e76SMat Martineau 		if (!tx_skb)
173918a48e76SMat Martineau 			break;
17400a708f8fSGustavo F. Padovan 
17411a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17420a708f8fSGustavo F. Padovan 
1743836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17446a026610SGustavo F. Padovan 		chan->unacked_frames++;
17456a026610SGustavo F. Padovan 		chan->frames_sent++;
174618a48e76SMat Martineau 		sent++;
17470a708f8fSGustavo F. Padovan 
174858d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
174958d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17500a708f8fSGustavo F. Padovan 		else
175158d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
175218a48e76SMat Martineau 
175318a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
175418a48e76SMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
17550a708f8fSGustavo F. Padovan 	}
17560a708f8fSGustavo F. Padovan 
175718a48e76SMat Martineau 	BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
175818a48e76SMat Martineau 	       (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
175918a48e76SMat Martineau 
176018a48e76SMat Martineau 	return sent;
17610a708f8fSGustavo F. Padovan }
17620a708f8fSGustavo F. Padovan 
1763e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1764e1fbd4c1SMat Martineau {
1765e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1766e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1767e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1768e1fbd4c1SMat Martineau 	u16 seq;
1769e1fbd4c1SMat Martineau 
1770e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1771e1fbd4c1SMat Martineau 
1772e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1773e1fbd4c1SMat Martineau 		return;
1774e1fbd4c1SMat Martineau 
1775e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1776e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1777e1fbd4c1SMat Martineau 
1778e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1779e1fbd4c1SMat Martineau 		if (!skb) {
1780e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
1781e1fbd4c1SMat Martineau 				seq);
1782e1fbd4c1SMat Martineau 			continue;
1783e1fbd4c1SMat Martineau 		}
1784e1fbd4c1SMat Martineau 
1785e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
1786e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
1787e1fbd4c1SMat Martineau 
1788e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
1789e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
1790e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
1791e1fbd4c1SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
1792e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1793e1fbd4c1SMat Martineau 			break;
1794e1fbd4c1SMat Martineau 		}
1795e1fbd4c1SMat Martineau 
1796e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
1797e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
1798e1fbd4c1SMat Martineau 			control.final = 1;
1799e1fbd4c1SMat Martineau 		else
1800e1fbd4c1SMat Martineau 			control.final = 0;
1801e1fbd4c1SMat Martineau 
1802e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
1803e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
1804e1fbd4c1SMat Martineau 			 * writeable copy
1805e1fbd4c1SMat Martineau 			 */
1806e1fbd4c1SMat Martineau 			tx_skb = skb_copy(skb, GFP_ATOMIC);
1807e1fbd4c1SMat Martineau 		} else {
1808e1fbd4c1SMat Martineau 			tx_skb = skb_clone(skb, GFP_ATOMIC);
1809e1fbd4c1SMat Martineau 		}
1810e1fbd4c1SMat Martineau 
1811e1fbd4c1SMat Martineau 		if (!tx_skb) {
1812e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1813e1fbd4c1SMat Martineau 			break;
1814e1fbd4c1SMat Martineau 		}
1815e1fbd4c1SMat Martineau 
1816e1fbd4c1SMat Martineau 		/* Update skb contents */
1817e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1818e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
1819e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1820e1fbd4c1SMat Martineau 		} else {
1821e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
1822e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1823e1fbd4c1SMat Martineau 		}
1824e1fbd4c1SMat Martineau 
1825e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
1826e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
1827e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
1828e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
1829e1fbd4c1SMat Martineau 		}
1830e1fbd4c1SMat Martineau 
1831e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
1832e1fbd4c1SMat Martineau 
1833e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
1834e1fbd4c1SMat Martineau 
1835e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
1836e1fbd4c1SMat Martineau 	}
1837e1fbd4c1SMat Martineau }
1838e1fbd4c1SMat Martineau 
1839d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
1840d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
1841d2a7ac5dSMat Martineau {
1842e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1843e1fbd4c1SMat Martineau 
1844e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1845e1fbd4c1SMat Martineau 
1846e1fbd4c1SMat Martineau 	if (control->poll)
1847e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
1848e1fbd4c1SMat Martineau 
1849e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
1850e1fbd4c1SMat Martineau 
1851e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1852e1fbd4c1SMat Martineau 		return;
1853e1fbd4c1SMat Martineau 
1854e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
1855e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
1856e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
1857e1fbd4c1SMat Martineau 				skb == chan->tx_send_head)
1858e1fbd4c1SMat Martineau 				break;
1859e1fbd4c1SMat Martineau 		}
1860e1fbd4c1SMat Martineau 
1861e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
1862e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
1863e1fbd4c1SMat Martineau 				break;
1864e1fbd4c1SMat Martineau 
1865e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
1866e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
1867e1fbd4c1SMat Martineau 		}
1868e1fbd4c1SMat Martineau 
1869e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
1870e1fbd4c1SMat Martineau 	}
1871d2a7ac5dSMat Martineau }
1872d2a7ac5dSMat Martineau 
1873b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1874b17e73bbSSzymon Janc {
18750a0aba42SMat Martineau 	struct l2cap_ctrl control;
18760a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
18770a0aba42SMat Martineau 					 chan->last_acked_seq);
18780a0aba42SMat Martineau 	int threshold;
18790a0aba42SMat Martineau 
18800a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
18810a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
18820a0aba42SMat Martineau 
18830a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
18840a0aba42SMat Martineau 	control.sframe = 1;
18850a0aba42SMat Martineau 
18860a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
18870a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
1888b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
18890a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
18900a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
18910a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
18920a0aba42SMat Martineau 	} else {
18930a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
18940a0aba42SMat Martineau 			l2cap_ertm_send(chan);
18950a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
18960a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
18970a0aba42SMat Martineau 				frames_to_ack = 0;
18980a0aba42SMat Martineau 		}
18990a0aba42SMat Martineau 
19000a0aba42SMat Martineau 		/* Ack now if the tx window is 3/4ths full.
19010a0aba42SMat Martineau 		 * Calculate without mul or div
19020a0aba42SMat Martineau 		 */
19030a0aba42SMat Martineau 		threshold = chan->tx_win;
19040a0aba42SMat Martineau 		threshold += threshold << 1;
19050a0aba42SMat Martineau 		threshold >>= 2;
19060a0aba42SMat Martineau 
19070a0aba42SMat Martineau 		BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
19080a0aba42SMat Martineau 		       threshold);
19090a0aba42SMat Martineau 
19100a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
19110a0aba42SMat Martineau 			__clear_ack_timer(chan);
19120a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
19130a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
19140a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
19150a0aba42SMat Martineau 			frames_to_ack = 0;
19160a0aba42SMat Martineau 		}
19170a0aba42SMat Martineau 
19180a0aba42SMat Martineau 		if (frames_to_ack)
19190a0aba42SMat Martineau 			__set_ack_timer(chan);
19200a0aba42SMat Martineau 	}
1921b17e73bbSSzymon Janc }
1922b17e73bbSSzymon Janc 
192304124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
192404124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
192504124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
19260a708f8fSGustavo F. Padovan {
19270952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
19280a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
192990338947SGustavo Padovan 	int sent = 0;
19300a708f8fSGustavo F. Padovan 
19310a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
19320a708f8fSGustavo F. Padovan 		return -EFAULT;
19330a708f8fSGustavo F. Padovan 
19340a708f8fSGustavo F. Padovan 	sent += count;
19350a708f8fSGustavo F. Padovan 	len  -= count;
19360a708f8fSGustavo F. Padovan 
19370a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
19380a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
19390a708f8fSGustavo F. Padovan 	while (len) {
1940fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1941fbe00700SGustavo Padovan 
19420a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
19430a708f8fSGustavo F. Padovan 
1944fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
194590338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1946fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1947fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
19482f7719ceSAndrei Emeltchenko 
1949fbe00700SGustavo Padovan 		*frag = tmp;
1950fbe00700SGustavo Padovan 
19510a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
19520a708f8fSGustavo F. Padovan 			return -EFAULT;
19530a708f8fSGustavo F. Padovan 
19545e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
19555e59b791SLuiz Augusto von Dentz 
19560a708f8fSGustavo F. Padovan 		sent += count;
19570a708f8fSGustavo F. Padovan 		len  -= count;
19580a708f8fSGustavo F. Padovan 
19592d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
19602d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
19612d0ed3d5SGustavo Padovan 
19620a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
19630a708f8fSGustavo F. Padovan 	}
19640a708f8fSGustavo F. Padovan 
19650a708f8fSGustavo F. Padovan 	return sent;
19660a708f8fSGustavo F. Padovan }
19670a708f8fSGustavo F. Padovan 
19685e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
19695e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19705e59b791SLuiz Augusto von Dentz 						u32 priority)
19710a708f8fSGustavo F. Padovan {
19728c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19730a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
197403a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
19750a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19760a708f8fSGustavo F. Padovan 
19776d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
19780a708f8fSGustavo F. Padovan 
19790a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19802f7719ceSAndrei Emeltchenko 
19812f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
198290338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
198390338947SGustavo Padovan 	if (IS_ERR(skb))
198490338947SGustavo Padovan 		return skb;
19850a708f8fSGustavo F. Padovan 
19865e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19875e59b791SLuiz Augusto von Dentz 
19880a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19890a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1990fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
1991daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1992daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
19930a708f8fSGustavo F. Padovan 
19940952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19950a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19960a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19970a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19980a708f8fSGustavo F. Padovan 	}
19990a708f8fSGustavo F. Padovan 	return skb;
20000a708f8fSGustavo F. Padovan }
20010a708f8fSGustavo F. Padovan 
20025e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
20035e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
20045e59b791SLuiz Augusto von Dentz 						u32 priority)
20050a708f8fSGustavo F. Padovan {
20068c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20070a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2008f2ba7faeSGustavo Padovan 	int err, count;
20090a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20100a708f8fSGustavo F. Padovan 
20116d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20120a708f8fSGustavo F. Padovan 
2013f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
20142f7719ceSAndrei Emeltchenko 
2015f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
201690338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
201790338947SGustavo Padovan 	if (IS_ERR(skb))
201890338947SGustavo Padovan 		return skb;
20190a708f8fSGustavo F. Padovan 
20205e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20215e59b791SLuiz Augusto von Dentz 
20220a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20230a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2024fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20256ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
20260a708f8fSGustavo F. Padovan 
20270952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20280a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20290a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20300a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20310a708f8fSGustavo F. Padovan 	}
20320a708f8fSGustavo F. Padovan 	return skb;
20330a708f8fSGustavo F. Padovan }
20340a708f8fSGustavo F. Padovan 
2035ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2036ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
203794122bbeSMat Martineau 						u16 sdulen)
20380a708f8fSGustavo F. Padovan {
20398c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20400a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2041e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
20420a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20430a708f8fSGustavo F. Padovan 
20446d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20450a708f8fSGustavo F. Padovan 
20460a708f8fSGustavo F. Padovan 	if (!conn)
20470a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
20480a708f8fSGustavo F. Padovan 
2049e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2050e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
2051e4ca6d98SAndrei Emeltchenko 	else
2052e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
2053e4ca6d98SAndrei Emeltchenko 
20540a708f8fSGustavo F. Padovan 	if (sdulen)
205503a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
20560a708f8fSGustavo F. Padovan 
205747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
205803a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
20590a708f8fSGustavo F. Padovan 
20600a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
20612f7719ceSAndrei Emeltchenko 
20622f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
206390338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
206490338947SGustavo Padovan 	if (IS_ERR(skb))
206590338947SGustavo Padovan 		return skb;
20660a708f8fSGustavo F. Padovan 
20670a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20680a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2069fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20700a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
207188843ab0SAndrei Emeltchenko 
207218a48e76SMat Martineau 	/* Control header is populated later */
207318a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
207418a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
207518a48e76SMat Martineau 	else
207618a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
207788843ab0SAndrei Emeltchenko 
20780a708f8fSGustavo F. Padovan 	if (sdulen)
207903a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
20800a708f8fSGustavo F. Padovan 
20810952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20820a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20830a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20840a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20850a708f8fSGustavo F. Padovan 	}
20860a708f8fSGustavo F. Padovan 
208718a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
20883ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
20890a708f8fSGustavo F. Padovan 	return skb;
20900a708f8fSGustavo F. Padovan }
20910a708f8fSGustavo F. Padovan 
209294122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
209394122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
209494122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
20950a708f8fSGustavo F. Padovan {
20960a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
209794122bbeSMat Martineau 	u16 sdu_len;
209894122bbeSMat Martineau 	size_t pdu_len;
209994122bbeSMat Martineau 	int err = 0;
210094122bbeSMat Martineau 	u8 sar;
21010a708f8fSGustavo F. Padovan 
210294122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
21030a708f8fSGustavo F. Padovan 
210494122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
210594122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
210694122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
210794122bbeSMat Martineau 	 */
210894122bbeSMat Martineau 
210994122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
211094122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
211194122bbeSMat Martineau 
211294122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
211394122bbeSMat Martineau 
211494122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
211594122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
211694122bbeSMat Martineau 
211794122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
211894122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
211994122bbeSMat Martineau 
212094122bbeSMat Martineau 	if (len <= pdu_len) {
212194122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
212294122bbeSMat Martineau 		sdu_len = 0;
212394122bbeSMat Martineau 		pdu_len = len;
212494122bbeSMat Martineau 	} else {
212594122bbeSMat Martineau 		sar = L2CAP_SAR_START;
212694122bbeSMat Martineau 		sdu_len = len;
212794122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
212894122bbeSMat Martineau 	}
21290a708f8fSGustavo F. Padovan 
21300a708f8fSGustavo F. Padovan 	while (len > 0) {
213194122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
21320a708f8fSGustavo F. Padovan 
21330a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
213494122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
21350a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
21360a708f8fSGustavo F. Padovan 		}
21370a708f8fSGustavo F. Padovan 
213894122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
213994122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
21400a708f8fSGustavo F. Padovan 
214194122bbeSMat Martineau 		len -= pdu_len;
214294122bbeSMat Martineau 		if (sdu_len) {
214394122bbeSMat Martineau 			sdu_len = 0;
214494122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
214594122bbeSMat Martineau 		}
214694122bbeSMat Martineau 
214794122bbeSMat Martineau 		if (len <= pdu_len) {
214894122bbeSMat Martineau 			sar = L2CAP_SAR_END;
214994122bbeSMat Martineau 			pdu_len = len;
215094122bbeSMat Martineau 		} else {
215194122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
215294122bbeSMat Martineau 		}
215394122bbeSMat Martineau 	}
215494122bbeSMat Martineau 
215594122bbeSMat Martineau 	return err;
21560a708f8fSGustavo F. Padovan }
21570a708f8fSGustavo F. Padovan 
21585e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
21595e59b791SLuiz Augusto von Dentz 								u32 priority)
21609a91a04aSGustavo F. Padovan {
21619a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
21629a91a04aSGustavo F. Padovan 	int err;
216394122bbeSMat Martineau 	struct sk_buff_head seg_queue;
21649a91a04aSGustavo F. Padovan 
21659a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2166715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
21675e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
21689a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21699a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21709a91a04aSGustavo F. Padovan 
21719a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21729a91a04aSGustavo F. Padovan 		return len;
21739a91a04aSGustavo F. Padovan 	}
21749a91a04aSGustavo F. Padovan 
21759a91a04aSGustavo F. Padovan 	switch (chan->mode) {
21769a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
21779a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
21789a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
21799a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
21809a91a04aSGustavo F. Padovan 
21819a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
21825e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
21839a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21849a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21859a91a04aSGustavo F. Padovan 
21869a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21879a91a04aSGustavo F. Padovan 		err = len;
21889a91a04aSGustavo F. Padovan 		break;
21899a91a04aSGustavo F. Padovan 
21909a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
21919a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
219294122bbeSMat Martineau 		/* Check outgoing MTU */
219394122bbeSMat Martineau 		if (len > chan->omtu) {
219494122bbeSMat Martineau 			err = -EMSGSIZE;
21959a91a04aSGustavo F. Padovan 			break;
21969a91a04aSGustavo F. Padovan 		}
21979a91a04aSGustavo F. Padovan 
219894122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
219994122bbeSMat Martineau 
220094122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
220194122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
220294122bbeSMat Martineau 		 * allocation.
220394122bbeSMat Martineau 		 */
220494122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
220594122bbeSMat Martineau 
220694122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
220794122bbeSMat Martineau 		 * check that it is still connected.
220894122bbeSMat Martineau 		 */
220994122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
221094122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
221194122bbeSMat Martineau 			err = -ENOTCONN;
22129a91a04aSGustavo F. Padovan 		}
22139a91a04aSGustavo F. Padovan 
221494122bbeSMat Martineau 		if (err)
221594122bbeSMat Martineau 			break;
221694122bbeSMat Martineau 
22173733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2218608bcc6dSMat Martineau 			err = l2cap_tx(chan, 0, &seg_queue,
2219608bcc6dSMat Martineau 				       L2CAP_EV_DATA_REQUEST);
22203733937dSMat Martineau 		else
22213733937dSMat Martineau 			err = l2cap_streaming_send(chan, &seg_queue);
222294122bbeSMat Martineau 
2223608bcc6dSMat Martineau 		if (!err)
22249a91a04aSGustavo F. Padovan 			err = len;
22259a91a04aSGustavo F. Padovan 
222694122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
222794122bbeSMat Martineau 		 * seg_queue and need to be purged.
222894122bbeSMat Martineau 		 */
222994122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
22309a91a04aSGustavo F. Padovan 		break;
22319a91a04aSGustavo F. Padovan 
22329a91a04aSGustavo F. Padovan 	default:
22339a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
22349a91a04aSGustavo F. Padovan 		err = -EBADFD;
22359a91a04aSGustavo F. Padovan 	}
22369a91a04aSGustavo F. Padovan 
22379a91a04aSGustavo F. Padovan 	return err;
22389a91a04aSGustavo F. Padovan }
22399a91a04aSGustavo F. Padovan 
2240d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2241d2a7ac5dSMat Martineau {
2242bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2243bed68bdeSMat Martineau 	u16 seq;
2244bed68bdeSMat Martineau 
2245bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2246bed68bdeSMat Martineau 
2247bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2248bed68bdeSMat Martineau 	control.sframe = 1;
2249bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2250bed68bdeSMat Martineau 
2251bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2252bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2253bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2254bed68bdeSMat Martineau 			control.reqseq = seq;
2255bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2256bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2257bed68bdeSMat Martineau 		}
2258bed68bdeSMat Martineau 	}
2259bed68bdeSMat Martineau 
2260bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2261d2a7ac5dSMat Martineau }
2262d2a7ac5dSMat Martineau 
2263d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2264d2a7ac5dSMat Martineau {
2265bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2266bed68bdeSMat Martineau 
2267bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2268bed68bdeSMat Martineau 
2269bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2270bed68bdeSMat Martineau 		return;
2271bed68bdeSMat Martineau 
2272bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2273bed68bdeSMat Martineau 	control.sframe = 1;
2274bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2275bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2276bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2277d2a7ac5dSMat Martineau }
2278d2a7ac5dSMat Martineau 
2279d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2280d2a7ac5dSMat Martineau {
2281bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2282bed68bdeSMat Martineau 	u16 initial_head;
2283bed68bdeSMat Martineau 	u16 seq;
2284bed68bdeSMat Martineau 
2285bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2286bed68bdeSMat Martineau 
2287bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2288bed68bdeSMat Martineau 	control.sframe = 1;
2289bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2290bed68bdeSMat Martineau 
2291bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2292bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2293bed68bdeSMat Martineau 
2294bed68bdeSMat Martineau 	do {
2295bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2296bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2297bed68bdeSMat Martineau 			break;
2298bed68bdeSMat Martineau 
2299bed68bdeSMat Martineau 		control.reqseq = seq;
2300bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2301bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2302bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2303d2a7ac5dSMat Martineau }
2304d2a7ac5dSMat Martineau 
2305608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2306608bcc6dSMat Martineau {
2307608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2308608bcc6dSMat Martineau 	u16 ackseq;
2309608bcc6dSMat Martineau 
2310608bcc6dSMat Martineau 	BT_DBG("chan %p, reqseq %d", chan, reqseq);
2311608bcc6dSMat Martineau 
2312608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2313608bcc6dSMat Martineau 		return;
2314608bcc6dSMat Martineau 
2315608bcc6dSMat Martineau 	BT_DBG("expected_ack_seq %d, unacked_frames %d",
2316608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2317608bcc6dSMat Martineau 
2318608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2319608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2320608bcc6dSMat Martineau 
2321608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2322608bcc6dSMat Martineau 		if (acked_skb) {
2323608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2324608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2325608bcc6dSMat Martineau 			chan->unacked_frames--;
2326608bcc6dSMat Martineau 		}
2327608bcc6dSMat Martineau 	}
2328608bcc6dSMat Martineau 
2329608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2330608bcc6dSMat Martineau 
2331608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2332608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2333608bcc6dSMat Martineau 
2334608bcc6dSMat Martineau 	BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
2335608bcc6dSMat Martineau }
2336608bcc6dSMat Martineau 
2337608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2338608bcc6dSMat Martineau {
2339608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2340608bcc6dSMat Martineau 
2341608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2342608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2343608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2344608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2345608bcc6dSMat Martineau }
2346608bcc6dSMat Martineau 
2347608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan,
2348608bcc6dSMat Martineau 			       struct l2cap_ctrl *control,
2349608bcc6dSMat Martineau 			       struct sk_buff_head *skbs, u8 event)
2350608bcc6dSMat Martineau {
2351608bcc6dSMat Martineau 	int err = 0;
2352608bcc6dSMat Martineau 
2353608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2354608bcc6dSMat Martineau 	       event);
2355608bcc6dSMat Martineau 
2356608bcc6dSMat Martineau 	switch (event) {
2357608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2358608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2359608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2360608bcc6dSMat Martineau 
2361608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2362608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2363608bcc6dSMat Martineau 		break;
2364608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2365608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2366608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2367608bcc6dSMat Martineau 
2368608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2369608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2370608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2371608bcc6dSMat Martineau 			 */
2372608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2373608bcc6dSMat Martineau 		}
2374608bcc6dSMat Martineau 
2375608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2376608bcc6dSMat Martineau 
2377608bcc6dSMat Martineau 		break;
2378608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2379608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2380608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2381608bcc6dSMat Martineau 
2382608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2383608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2384608bcc6dSMat Martineau 
2385608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2386608bcc6dSMat Martineau 			local_control.sframe = 1;
2387608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2388608bcc6dSMat Martineau 			local_control.poll = 1;
2389608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2390a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2391608bcc6dSMat Martineau 
2392608bcc6dSMat Martineau 			chan->retry_count = 1;
2393608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2394608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2395608bcc6dSMat Martineau 		}
2396608bcc6dSMat Martineau 		break;
2397608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2398608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2399608bcc6dSMat Martineau 		break;
2400608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2401608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2402608bcc6dSMat Martineau 		chan->retry_count = 1;
2403608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2404608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2405608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2406608bcc6dSMat Martineau 		break;
2407608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2408608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2409608bcc6dSMat Martineau 		chan->retry_count = 1;
2410608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2411608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2412608bcc6dSMat Martineau 		break;
2413608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2414608bcc6dSMat Martineau 		/* Nothing to process */
2415608bcc6dSMat Martineau 		break;
2416608bcc6dSMat Martineau 	default:
2417608bcc6dSMat Martineau 		break;
2418608bcc6dSMat Martineau 	}
2419608bcc6dSMat Martineau 
2420608bcc6dSMat Martineau 	return err;
2421608bcc6dSMat Martineau }
2422608bcc6dSMat Martineau 
2423608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2424608bcc6dSMat Martineau 				 struct l2cap_ctrl *control,
2425608bcc6dSMat Martineau 				 struct sk_buff_head *skbs, u8 event)
2426608bcc6dSMat Martineau {
2427608bcc6dSMat Martineau 	int err = 0;
2428608bcc6dSMat Martineau 
2429608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2430608bcc6dSMat Martineau 	       event);
2431608bcc6dSMat Martineau 
2432608bcc6dSMat Martineau 	switch (event) {
2433608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2434608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2435608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2436608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2437608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2438608bcc6dSMat Martineau 		break;
2439608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2440608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2441608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2442608bcc6dSMat Martineau 
2443608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2444608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2445608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2446608bcc6dSMat Martineau 			 */
2447608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2448608bcc6dSMat Martineau 		}
2449608bcc6dSMat Martineau 
2450608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2451608bcc6dSMat Martineau 
2452608bcc6dSMat Martineau 		break;
2453608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2454608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2455608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2456608bcc6dSMat Martineau 
2457608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2458608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2459608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2460608bcc6dSMat Martineau 			local_control.sframe = 1;
2461608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2462608bcc6dSMat Martineau 			local_control.poll = 1;
2463608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2464a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2465608bcc6dSMat Martineau 
2466608bcc6dSMat Martineau 			chan->retry_count = 1;
2467608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2468608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2469608bcc6dSMat Martineau 		}
2470608bcc6dSMat Martineau 		break;
2471608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2472608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2473608bcc6dSMat Martineau 
2474608bcc6dSMat Martineau 		/* Fall through */
2475608bcc6dSMat Martineau 
2476608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2477608bcc6dSMat Martineau 		if (control && control->final) {
2478608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2479608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2480608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2481608bcc6dSMat Martineau 			chan->retry_count = 0;
2482608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2483608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2484608bcc6dSMat Martineau 		}
2485608bcc6dSMat Martineau 		break;
2486608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2487608bcc6dSMat Martineau 		/* Ignore */
2488608bcc6dSMat Martineau 		break;
2489608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2490608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2491608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2492608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2493608bcc6dSMat Martineau 			chan->retry_count++;
2494608bcc6dSMat Martineau 		} else {
2495608bcc6dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2496608bcc6dSMat Martineau 		}
2497608bcc6dSMat Martineau 		break;
2498608bcc6dSMat Martineau 	default:
2499608bcc6dSMat Martineau 		break;
2500608bcc6dSMat Martineau 	}
2501608bcc6dSMat Martineau 
2502608bcc6dSMat Martineau 	return err;
2503608bcc6dSMat Martineau }
2504608bcc6dSMat Martineau 
2505608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2506608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event)
2507608bcc6dSMat Martineau {
2508608bcc6dSMat Martineau 	int err = 0;
2509608bcc6dSMat Martineau 
2510608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2511608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2512608bcc6dSMat Martineau 
2513608bcc6dSMat Martineau 	switch (chan->tx_state) {
2514608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2515608bcc6dSMat Martineau 		err = l2cap_tx_state_xmit(chan, control, skbs, event);
2516608bcc6dSMat Martineau 		break;
2517608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2518608bcc6dSMat Martineau 		err = l2cap_tx_state_wait_f(chan, control, skbs, event);
2519608bcc6dSMat Martineau 		break;
2520608bcc6dSMat Martineau 	default:
2521608bcc6dSMat Martineau 		/* Ignore event */
2522608bcc6dSMat Martineau 		break;
2523608bcc6dSMat Martineau 	}
2524608bcc6dSMat Martineau 
2525608bcc6dSMat Martineau 	return err;
2526608bcc6dSMat Martineau }
2527608bcc6dSMat Martineau 
25284b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
25294b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
25304b51dae9SMat Martineau {
25314b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
25324b51dae9SMat Martineau 	l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
25334b51dae9SMat Martineau }
25344b51dae9SMat Martineau 
25350a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
25360a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
25370a708f8fSGustavo F. Padovan {
25380a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
253948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
25400a708f8fSGustavo F. Padovan 
25410a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
25420a708f8fSGustavo F. Padovan 
25433df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
25443d57dc68SGustavo F. Padovan 
25453df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
254648454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2547715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
25480a708f8fSGustavo F. Padovan 			continue;
25490a708f8fSGustavo F. Padovan 
25500a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
25510a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
25520a708f8fSGustavo F. Padovan 			continue;
25530a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
25540a708f8fSGustavo F. Padovan 		if (!nskb)
25550a708f8fSGustavo F. Padovan 			continue;
25560a708f8fSGustavo F. Padovan 
255723070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
25580a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
25590a708f8fSGustavo F. Padovan 	}
25603d57dc68SGustavo F. Padovan 
25613df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
25620a708f8fSGustavo F. Padovan }
25630a708f8fSGustavo F. Padovan 
25640a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
25650a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
25660a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
25670a708f8fSGustavo F. Padovan {
25680a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
25690a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
25700a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
25710a708f8fSGustavo F. Padovan 	int len, count;
25720a708f8fSGustavo F. Padovan 
25730a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
25740a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
25750a708f8fSGustavo F. Padovan 
25760a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
25770a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
25780a708f8fSGustavo F. Padovan 
25790a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
25800a708f8fSGustavo F. Padovan 	if (!skb)
25810a708f8fSGustavo F. Padovan 		return NULL;
25820a708f8fSGustavo F. Padovan 
25830a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
25840a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
25853300d9a9SClaudio Takahasi 
25863300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
25873300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
25883300d9a9SClaudio Takahasi 	else
25890a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
25900a708f8fSGustavo F. Padovan 
25910a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
25920a708f8fSGustavo F. Padovan 	cmd->code  = code;
25930a708f8fSGustavo F. Padovan 	cmd->ident = ident;
25940a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
25950a708f8fSGustavo F. Padovan 
25960a708f8fSGustavo F. Padovan 	if (dlen) {
25970a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
25980a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
25990a708f8fSGustavo F. Padovan 		data += count;
26000a708f8fSGustavo F. Padovan 	}
26010a708f8fSGustavo F. Padovan 
26020a708f8fSGustavo F. Padovan 	len -= skb->len;
26030a708f8fSGustavo F. Padovan 
26040a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
26050a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
26060a708f8fSGustavo F. Padovan 	while (len) {
26070a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
26080a708f8fSGustavo F. Padovan 
26090a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
26100a708f8fSGustavo F. Padovan 		if (!*frag)
26110a708f8fSGustavo F. Padovan 			goto fail;
26120a708f8fSGustavo F. Padovan 
26130a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
26140a708f8fSGustavo F. Padovan 
26150a708f8fSGustavo F. Padovan 		len  -= count;
26160a708f8fSGustavo F. Padovan 		data += count;
26170a708f8fSGustavo F. Padovan 
26180a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
26190a708f8fSGustavo F. Padovan 	}
26200a708f8fSGustavo F. Padovan 
26210a708f8fSGustavo F. Padovan 	return skb;
26220a708f8fSGustavo F. Padovan 
26230a708f8fSGustavo F. Padovan fail:
26240a708f8fSGustavo F. Padovan 	kfree_skb(skb);
26250a708f8fSGustavo F. Padovan 	return NULL;
26260a708f8fSGustavo F. Padovan }
26270a708f8fSGustavo F. Padovan 
26280a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
26290a708f8fSGustavo F. Padovan {
26300a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26310a708f8fSGustavo F. Padovan 	int len;
26320a708f8fSGustavo F. Padovan 
26330a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
26340a708f8fSGustavo F. Padovan 	*ptr += len;
26350a708f8fSGustavo F. Padovan 
26360a708f8fSGustavo F. Padovan 	*type = opt->type;
26370a708f8fSGustavo F. Padovan 	*olen = opt->len;
26380a708f8fSGustavo F. Padovan 
26390a708f8fSGustavo F. Padovan 	switch (opt->len) {
26400a708f8fSGustavo F. Padovan 	case 1:
26410a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
26420a708f8fSGustavo F. Padovan 		break;
26430a708f8fSGustavo F. Padovan 
26440a708f8fSGustavo F. Padovan 	case 2:
26450a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
26460a708f8fSGustavo F. Padovan 		break;
26470a708f8fSGustavo F. Padovan 
26480a708f8fSGustavo F. Padovan 	case 4:
26490a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
26500a708f8fSGustavo F. Padovan 		break;
26510a708f8fSGustavo F. Padovan 
26520a708f8fSGustavo F. Padovan 	default:
26530a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
26540a708f8fSGustavo F. Padovan 		break;
26550a708f8fSGustavo F. Padovan 	}
26560a708f8fSGustavo F. Padovan 
26570a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
26580a708f8fSGustavo F. Padovan 	return len;
26590a708f8fSGustavo F. Padovan }
26600a708f8fSGustavo F. Padovan 
26610a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
26620a708f8fSGustavo F. Padovan {
26630a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26640a708f8fSGustavo F. Padovan 
26650a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
26660a708f8fSGustavo F. Padovan 
26670a708f8fSGustavo F. Padovan 	opt->type = type;
26680a708f8fSGustavo F. Padovan 	opt->len  = len;
26690a708f8fSGustavo F. Padovan 
26700a708f8fSGustavo F. Padovan 	switch (len) {
26710a708f8fSGustavo F. Padovan 	case 1:
26720a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
26730a708f8fSGustavo F. Padovan 		break;
26740a708f8fSGustavo F. Padovan 
26750a708f8fSGustavo F. Padovan 	case 2:
26760a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
26770a708f8fSGustavo F. Padovan 		break;
26780a708f8fSGustavo F. Padovan 
26790a708f8fSGustavo F. Padovan 	case 4:
26800a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
26810a708f8fSGustavo F. Padovan 		break;
26820a708f8fSGustavo F. Padovan 
26830a708f8fSGustavo F. Padovan 	default:
26840a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
26850a708f8fSGustavo F. Padovan 		break;
26860a708f8fSGustavo F. Padovan 	}
26870a708f8fSGustavo F. Padovan 
26880a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
26890a708f8fSGustavo F. Padovan }
26900a708f8fSGustavo F. Padovan 
2691f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2692f89cef09SAndrei Emeltchenko {
2693f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2694f89cef09SAndrei Emeltchenko 
2695f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2696f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2697f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2698f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2699f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2700f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2701f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2702f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2703f89cef09SAndrei Emeltchenko 		break;
2704f89cef09SAndrei Emeltchenko 
2705f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2706f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2707f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2708f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2709f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2710f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2711f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2712f89cef09SAndrei Emeltchenko 		break;
2713f89cef09SAndrei Emeltchenko 
2714f89cef09SAndrei Emeltchenko 	default:
2715f89cef09SAndrei Emeltchenko 		return;
2716f89cef09SAndrei Emeltchenko 	}
2717f89cef09SAndrei Emeltchenko 
2718f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2719f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2720f89cef09SAndrei Emeltchenko }
2721f89cef09SAndrei Emeltchenko 
2722721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
27230a708f8fSGustavo F. Padovan {
2724721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2725721c4181SGustavo F. Padovan 							ack_timer.work);
27260a708f8fSGustavo F. Padovan 
27272fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27282fb9b3d4SGustavo F. Padovan 
27296be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
27306be36555SAndrei Emeltchenko 
27310a0aba42SMat Martineau 	l2cap_send_ack(chan);
27326be36555SAndrei Emeltchenko 
27336be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
273409bfb2eeSSzymon Janc 
273509bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
27360a708f8fSGustavo F. Padovan }
27370a708f8fSGustavo F. Padovan 
27383c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
27390a708f8fSGustavo F. Padovan {
27403c588192SMat Martineau 	int err;
27413c588192SMat Martineau 
2742105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2743105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
274442e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
27456a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
274642e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
27476a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2748105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2749105bdf9eSMat Martineau 	chan->sdu = NULL;
2750105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2751105bdf9eSMat Martineau 	chan->sdu_len = 0;
2752105bdf9eSMat Martineau 
2753d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2754d34c34fbSMat Martineau 
2755105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2756105bdf9eSMat Martineau 		return 0;
2757105bdf9eSMat Martineau 
2758105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2759105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
27600a708f8fSGustavo F. Padovan 
2761721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2762721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2763721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
27640a708f8fSGustavo F. Padovan 
2765f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
27660a708f8fSGustavo F. Padovan 
27673c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
27683c588192SMat Martineau 	if (err < 0)
27693c588192SMat Martineau 		return err;
27703c588192SMat Martineau 
27719dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
27729dc9affcSMat Martineau 	if (err < 0)
27739dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
27749dc9affcSMat Martineau 
27759dc9affcSMat Martineau 	return err;
27760a708f8fSGustavo F. Padovan }
27770a708f8fSGustavo F. Padovan 
27780a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
27790a708f8fSGustavo F. Padovan {
27800a708f8fSGustavo F. Padovan 	switch (mode) {
27810a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
27820a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27830a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
27840a708f8fSGustavo F. Padovan 			return mode;
27850a708f8fSGustavo F. Padovan 		/* fall through */
27860a708f8fSGustavo F. Padovan 	default:
27870a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
27880a708f8fSGustavo F. Padovan 	}
27890a708f8fSGustavo F. Padovan }
27900a708f8fSGustavo F. Padovan 
27916327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
27926327eb98SAndrei Emeltchenko {
27936327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
27946327eb98SAndrei Emeltchenko }
27956327eb98SAndrei Emeltchenko 
2796f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2797f89cef09SAndrei Emeltchenko {
2798f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2799f89cef09SAndrei Emeltchenko }
2800f89cef09SAndrei Emeltchenko 
28016327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
28026327eb98SAndrei Emeltchenko {
28036327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2804836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
28056327eb98SAndrei Emeltchenko 		/* use extended control field */
28066327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2807836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2808836be934SAndrei Emeltchenko 	} else {
28096327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
28106327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2811836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2812836be934SAndrei Emeltchenko 	}
28136327eb98SAndrei Emeltchenko }
28146327eb98SAndrei Emeltchenko 
2815710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
28160a708f8fSGustavo F. Padovan {
28170a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
28180c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
28190a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2820c8f79162SAndrei Emeltchenko 	u16 size;
28210a708f8fSGustavo F. Padovan 
282249208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
28230a708f8fSGustavo F. Padovan 
282473ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
28250a708f8fSGustavo F. Padovan 		goto done;
28260a708f8fSGustavo F. Padovan 
28270c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28290a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2830c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
28310a708f8fSGustavo F. Padovan 			break;
28320a708f8fSGustavo F. Padovan 
2833f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2834f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2835f89cef09SAndrei Emeltchenko 
28360a708f8fSGustavo F. Padovan 		/* fall through */
28370a708f8fSGustavo F. Padovan 	default:
28388c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
28390a708f8fSGustavo F. Padovan 		break;
28400a708f8fSGustavo F. Padovan 	}
28410a708f8fSGustavo F. Padovan 
28420a708f8fSGustavo F. Padovan done:
28430c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
28440c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
28450a708f8fSGustavo F. Padovan 
28460c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28470a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
28488c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
28498c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
28500a708f8fSGustavo F. Padovan 			break;
28510a708f8fSGustavo F. Padovan 
28520a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
28530a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
28540a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
28550a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28560a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
28570a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
28580a708f8fSGustavo F. Padovan 
28590a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28600a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28610a708f8fSGustavo F. Padovan 		break;
28620a708f8fSGustavo F. Padovan 
28630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
28640a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
286547d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
28660a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28670a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2868c8f79162SAndrei Emeltchenko 
2869c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2870c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2871c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2872c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2873c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
28740a708f8fSGustavo F. Padovan 
28756327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
28766327eb98SAndrei Emeltchenko 
28776327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
28786327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
28790a708f8fSGustavo F. Padovan 
28800a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28810a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28820a708f8fSGustavo F. Padovan 
2883f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2884f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2885f89cef09SAndrei Emeltchenko 
28868c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
28870a708f8fSGustavo F. Padovan 			break;
28880a708f8fSGustavo F. Padovan 
288947d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2890c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
289147d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
289247d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
28930a708f8fSGustavo F. Padovan 		}
28946327eb98SAndrei Emeltchenko 
28956327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
28966327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
28976327eb98SAndrei Emeltchenko 								chan->tx_win);
28980a708f8fSGustavo F. Padovan 		break;
28990a708f8fSGustavo F. Padovan 
29000a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
29010a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
29020a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
29030a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
29040a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
29050a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2906c8f79162SAndrei Emeltchenko 
2907c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2908c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2909c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2910c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2911c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
29120a708f8fSGustavo F. Padovan 
29130a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
29140a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
29150a708f8fSGustavo F. Padovan 
2916f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2917f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2918f89cef09SAndrei Emeltchenko 
29198c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29200a708f8fSGustavo F. Padovan 			break;
29210a708f8fSGustavo F. Padovan 
292247d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2923c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
292447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
292547d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29260a708f8fSGustavo F. Padovan 		}
29270a708f8fSGustavo F. Padovan 		break;
29280a708f8fSGustavo F. Padovan 	}
29290a708f8fSGustavo F. Padovan 
2930fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
29310a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
29320a708f8fSGustavo F. Padovan 
29330a708f8fSGustavo F. Padovan 	return ptr - data;
29340a708f8fSGustavo F. Padovan }
29350a708f8fSGustavo F. Padovan 
293673ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
29370a708f8fSGustavo F. Padovan {
29380a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
29390a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
294073ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
294173ffa904SGustavo F. Padovan 	int len = chan->conf_len;
29420a708f8fSGustavo F. Padovan 	int type, hint, olen;
29430a708f8fSGustavo F. Padovan 	unsigned long val;
29440a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
294542dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
294642dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
29470a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
29480a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2949c8f79162SAndrei Emeltchenko 	u16 size;
29500a708f8fSGustavo F. Padovan 
295173ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
29520a708f8fSGustavo F. Padovan 
29530a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29540a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
29550a708f8fSGustavo F. Padovan 
29560a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
29570a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
29580a708f8fSGustavo F. Padovan 
29590a708f8fSGustavo F. Padovan 		switch (type) {
29600a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
29610a708f8fSGustavo F. Padovan 			mtu = val;
29620a708f8fSGustavo F. Padovan 			break;
29630a708f8fSGustavo F. Padovan 
29640a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
29650c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
29660a708f8fSGustavo F. Padovan 			break;
29670a708f8fSGustavo F. Padovan 
29680a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
29690a708f8fSGustavo F. Padovan 			break;
29700a708f8fSGustavo F. Padovan 
29710a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29720a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29730a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
29740a708f8fSGustavo F. Padovan 			break;
29750a708f8fSGustavo F. Padovan 
29760a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
29770a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2978c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
297942dceae2SAndrei Emeltchenko 			break;
29800a708f8fSGustavo F. Padovan 
298142dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
298242dceae2SAndrei Emeltchenko 			remote_efs = 1;
298342dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
298442dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
29850a708f8fSGustavo F. Padovan 			break;
29860a708f8fSGustavo F. Padovan 
29876327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
29886327eb98SAndrei Emeltchenko 			if (!enable_hs)
29896327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
29906327eb98SAndrei Emeltchenko 
29916327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
29926327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2993836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
29946327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
29950a708f8fSGustavo F. Padovan 			break;
29960a708f8fSGustavo F. Padovan 
29970a708f8fSGustavo F. Padovan 		default:
29980a708f8fSGustavo F. Padovan 			if (hint)
29990a708f8fSGustavo F. Padovan 				break;
30000a708f8fSGustavo F. Padovan 
30010a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
30020a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
30030a708f8fSGustavo F. Padovan 			break;
30040a708f8fSGustavo F. Padovan 		}
30050a708f8fSGustavo F. Padovan 	}
30060a708f8fSGustavo F. Padovan 
300773ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
30080a708f8fSGustavo F. Padovan 		goto done;
30090a708f8fSGustavo F. Padovan 
30100c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
30110a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
30120a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3013c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
30140c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
30158c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
30160a708f8fSGustavo F. Padovan 			break;
30170a708f8fSGustavo F. Padovan 		}
30180a708f8fSGustavo F. Padovan 
301942dceae2SAndrei Emeltchenko 		if (remote_efs) {
302042dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
302142dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
302242dceae2SAndrei Emeltchenko 			else
302342dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
302442dceae2SAndrei Emeltchenko 		}
302542dceae2SAndrei Emeltchenko 
30260c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
30270a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30280a708f8fSGustavo F. Padovan 
30290a708f8fSGustavo F. Padovan 		break;
30300a708f8fSGustavo F. Padovan 	}
30310a708f8fSGustavo F. Padovan 
30320a708f8fSGustavo F. Padovan done:
30330c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
30340a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
30350c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
30360a708f8fSGustavo F. Padovan 
303773ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
30380a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30390a708f8fSGustavo F. Padovan 
30400a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
30410a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
30420a708f8fSGustavo F. Padovan 	}
30430a708f8fSGustavo F. Padovan 
30440a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
30450a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
30460a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
30470a708f8fSGustavo F. Padovan 
30480a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
30490a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
30500a708f8fSGustavo F. Padovan 		else {
30510c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3052c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
30530a708f8fSGustavo F. Padovan 		}
30540c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
30550a708f8fSGustavo F. Padovan 
305642dceae2SAndrei Emeltchenko 		if (remote_efs) {
305742dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
305842dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
305942dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
306042dceae2SAndrei Emeltchenko 
306142dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
306242dceae2SAndrei Emeltchenko 
306342dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
306442dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
306542dceae2SAndrei Emeltchenko 
306642dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
306742dceae2SAndrei Emeltchenko 							sizeof(efs),
306842dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
30690e8b207eSAndrei Emeltchenko 			} else {
30703e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
30710e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
30720e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
307342dceae2SAndrei Emeltchenko 			}
307442dceae2SAndrei Emeltchenko 		}
307542dceae2SAndrei Emeltchenko 
30760a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
30770a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
307847d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3079c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
30800a708f8fSGustavo F. Padovan 			break;
30810a708f8fSGustavo F. Padovan 
30820a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
30836327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
30842c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
30856327eb98SAndrei Emeltchenko 			else
30866327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
30876327eb98SAndrei Emeltchenko 
30882c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
30890a708f8fSGustavo F. Padovan 
3090c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3091c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3092c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3093c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3094c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3095c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3096c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
30994fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
31000a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
31014fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
31020a708f8fSGustavo F. Padovan 
3103c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31040a708f8fSGustavo F. Padovan 
31050a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31060a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31070a708f8fSGustavo F. Padovan 
310842dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
310942dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
311042dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
311142dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
311242dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
311342dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
311442dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
311542dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
311642dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
311742dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
311842dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
311942dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
312042dceae2SAndrei Emeltchenko 			}
31210a708f8fSGustavo F. Padovan 			break;
31220a708f8fSGustavo F. Padovan 
31230a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3124c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3125c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3126c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3127c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3128c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3129c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3130c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31310a708f8fSGustavo F. Padovan 
3132c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31330a708f8fSGustavo F. Padovan 
31340a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31350a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31360a708f8fSGustavo F. Padovan 
31370a708f8fSGustavo F. Padovan 			break;
31380a708f8fSGustavo F. Padovan 
31390a708f8fSGustavo F. Padovan 		default:
31400a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
31410a708f8fSGustavo F. Padovan 
31420a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
31430c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
31440a708f8fSGustavo F. Padovan 		}
31450a708f8fSGustavo F. Padovan 
31460a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3147c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
31480a708f8fSGustavo F. Padovan 	}
3149fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
31500a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
31510a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
31520a708f8fSGustavo F. Padovan 
31530a708f8fSGustavo F. Padovan 	return ptr - data;
31540a708f8fSGustavo F. Padovan }
31550a708f8fSGustavo F. Padovan 
3156b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
31570a708f8fSGustavo F. Padovan {
31580a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
31590a708f8fSGustavo F. Padovan 	void *ptr = req->data;
31600a708f8fSGustavo F. Padovan 	int type, olen;
31610a708f8fSGustavo F. Padovan 	unsigned long val;
316236e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
316366af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
31640a708f8fSGustavo F. Padovan 
3165fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
31660a708f8fSGustavo F. Padovan 
31670a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
31680a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
31690a708f8fSGustavo F. Padovan 
31700a708f8fSGustavo F. Padovan 		switch (type) {
31710a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
31720a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
31730a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
31740c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
31750a708f8fSGustavo F. Padovan 			} else
31760c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
31770c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
31780a708f8fSGustavo F. Padovan 			break;
31790a708f8fSGustavo F. Padovan 
31800a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
31810c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
31820a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
31830c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
31840a708f8fSGustavo F. Padovan 			break;
31850a708f8fSGustavo F. Padovan 
31860a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
31870a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
31880a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
31890a708f8fSGustavo F. Padovan 
3190c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
31910c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
31920a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
31930a708f8fSGustavo F. Padovan 
319447d1ec61SGustavo F. Padovan 			chan->fcs = 0;
31950a708f8fSGustavo F. Padovan 
31960a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31970a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31980a708f8fSGustavo F. Padovan 			break;
31996327eb98SAndrei Emeltchenko 
32006327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
32016327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
32026327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
32033e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
32043e6b3b95SGustavo F. Padovan 							chan->tx_win);
32056327eb98SAndrei Emeltchenko 			break;
320666af7aafSAndrei Emeltchenko 
320766af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
320866af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
320966af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
321066af7aafSAndrei Emeltchenko 
321166af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
321266af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
321366af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
321466af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
321566af7aafSAndrei Emeltchenko 
321666af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
321766af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
321866af7aafSAndrei Emeltchenko 			break;
32190a708f8fSGustavo F. Padovan 		}
32200a708f8fSGustavo F. Padovan 	}
32210a708f8fSGustavo F. Padovan 
32220c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
32230a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
32240a708f8fSGustavo F. Padovan 
32250c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
32260a708f8fSGustavo F. Padovan 
32270e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
32280a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
32290a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
323047d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
323147d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
323247d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
323366af7aafSAndrei Emeltchenko 
323466af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
323566af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
323666af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
323766af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
323866af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
323966af7aafSAndrei Emeltchenko 				chan->local_flush_to =
324066af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
324166af7aafSAndrei Emeltchenko 			}
32420a708f8fSGustavo F. Padovan 			break;
324366af7aafSAndrei Emeltchenko 
32440a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
324547d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
32460a708f8fSGustavo F. Padovan 		}
32470a708f8fSGustavo F. Padovan 	}
32480a708f8fSGustavo F. Padovan 
3249fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
32500a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
32510a708f8fSGustavo F. Padovan 
32520a708f8fSGustavo F. Padovan 	return ptr - data;
32530a708f8fSGustavo F. Padovan }
32540a708f8fSGustavo F. Padovan 
3255fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
32560a708f8fSGustavo F. Padovan {
32570a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
32580a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
32590a708f8fSGustavo F. Padovan 
3260fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32610a708f8fSGustavo F. Padovan 
3262fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
32630a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
32640a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
32650a708f8fSGustavo F. Padovan 
32660a708f8fSGustavo F. Padovan 	return ptr - data;
32670a708f8fSGustavo F. Padovan }
32680a708f8fSGustavo F. Padovan 
32698c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3270710f9b0aSGustavo F. Padovan {
3271710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
32728c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3273710f9b0aSGustavo F. Padovan 	u8 buf[128];
3274710f9b0aSGustavo F. Padovan 
3275fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3276fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3277710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3278710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3279710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
3280710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3281710f9b0aSGustavo F. Padovan 
3282c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3283710f9b0aSGustavo F. Padovan 		return;
3284710f9b0aSGustavo F. Padovan 
3285710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3286710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
3287710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3288710f9b0aSGustavo F. Padovan }
3289710f9b0aSGustavo F. Padovan 
329047d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
32910a708f8fSGustavo F. Padovan {
32920a708f8fSGustavo F. Padovan 	int type, olen;
32930a708f8fSGustavo F. Padovan 	unsigned long val;
32940a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
32950a708f8fSGustavo F. Padovan 
329647d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
32970a708f8fSGustavo F. Padovan 
32980c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
32990a708f8fSGustavo F. Padovan 		return;
33000a708f8fSGustavo F. Padovan 
33010a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33020a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
33030a708f8fSGustavo F. Padovan 
33040a708f8fSGustavo F. Padovan 		switch (type) {
33050a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
33060a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
33070a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
33080a708f8fSGustavo F. Padovan 			goto done;
33090a708f8fSGustavo F. Padovan 		}
33100a708f8fSGustavo F. Padovan 	}
33110a708f8fSGustavo F. Padovan 
331236e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
331336e999a8SMat Martineau 	 * did not send an RFC option.
331436e999a8SMat Martineau 	 */
331536e999a8SMat Martineau 	rfc.mode = chan->mode;
331636e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
331736e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
331836e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
331936e999a8SMat Martineau 
332036e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
332136e999a8SMat Martineau 
33220a708f8fSGustavo F. Padovan done:
33230a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
33240a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
332547d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
332647d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
332747d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33280a708f8fSGustavo F. Padovan 		break;
33290a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
333047d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33310a708f8fSGustavo F. Padovan 	}
33320a708f8fSGustavo F. Padovan }
33330a708f8fSGustavo F. Padovan 
33340a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33350a708f8fSGustavo F. Padovan {
3336e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
33370a708f8fSGustavo F. Padovan 
3338e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
33390a708f8fSGustavo F. Padovan 		return 0;
33400a708f8fSGustavo F. Padovan 
33410a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
33420a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
334317cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
33440a708f8fSGustavo F. Padovan 
33450a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
33460a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
33470a708f8fSGustavo F. Padovan 
33480a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
33490a708f8fSGustavo F. Padovan 	}
33500a708f8fSGustavo F. Padovan 
33510a708f8fSGustavo F. Padovan 	return 0;
33520a708f8fSGustavo F. Padovan }
33530a708f8fSGustavo F. Padovan 
33540a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33550a708f8fSGustavo F. Padovan {
33560a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
33570a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
335823691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
33590a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
33600a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
33610a708f8fSGustavo F. Padovan 
33620a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
33630a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
33640a708f8fSGustavo F. Padovan 
3365097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
33660a708f8fSGustavo F. Padovan 
33670a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
3368c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
336923691d75SGustavo F. Padovan 	if (!pchan) {
33700a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
33710a708f8fSGustavo F. Padovan 		goto sendresp;
33720a708f8fSGustavo F. Padovan 	}
33730a708f8fSGustavo F. Padovan 
337423691d75SGustavo F. Padovan 	parent = pchan->sk;
337523691d75SGustavo F. Padovan 
33763df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3377aa2ac881SGustavo F. Padovan 	lock_sock(parent);
33780a708f8fSGustavo F. Padovan 
33790a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
33800a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
33810a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
33829f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
33830a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
33840a708f8fSGustavo F. Padovan 		goto response;
33850a708f8fSGustavo F. Padovan 	}
33860a708f8fSGustavo F. Padovan 
33870a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
33880a708f8fSGustavo F. Padovan 
33890a708f8fSGustavo F. Padovan 	/* Check for backlog size */
33900a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
33910a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
33920a708f8fSGustavo F. Padovan 		goto response;
33930a708f8fSGustavo F. Padovan 	}
33940a708f8fSGustavo F. Padovan 
339580808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
339680808e43SGustavo F. Padovan 	if (!chan)
33970a708f8fSGustavo F. Padovan 		goto response;
33980a708f8fSGustavo F. Padovan 
339980808e43SGustavo F. Padovan 	sk = chan->sk;
340080808e43SGustavo F. Padovan 
34010a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3402baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
34030a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3404ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
34050a708f8fSGustavo F. Padovan 		goto response;
34060a708f8fSGustavo F. Padovan 	}
34070a708f8fSGustavo F. Padovan 
34080a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
34090a708f8fSGustavo F. Padovan 
34100a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
34110a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3412fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3413fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
34140a708f8fSGustavo F. Padovan 
3415d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3416d1010240SGustavo F. Padovan 
34176be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
341848454079SGustavo F. Padovan 
3419fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
34200a708f8fSGustavo F. Padovan 
3421c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
34220a708f8fSGustavo F. Padovan 
3423fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
34240a708f8fSGustavo F. Padovan 
34250a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3426d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3427c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
34280e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
34290a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
34300a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
34310a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
34320a708f8fSGustavo F. Padovan 			} else {
34330e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
34340a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
34350a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
34360a708f8fSGustavo F. Padovan 			}
34370a708f8fSGustavo F. Padovan 		} else {
34380e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
34390a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
34400a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
34410a708f8fSGustavo F. Padovan 		}
34420a708f8fSGustavo F. Padovan 	} else {
34430e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
34440a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
34450a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
34460a708f8fSGustavo F. Padovan 	}
34470a708f8fSGustavo F. Padovan 
34480a708f8fSGustavo F. Padovan response:
3449aa2ac881SGustavo F. Padovan 	release_sock(parent);
34503df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34510a708f8fSGustavo F. Padovan 
34520a708f8fSGustavo F. Padovan sendresp:
34530a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
34540a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
34550a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
34560a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
34570a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
34580a708f8fSGustavo F. Padovan 
34590a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
34600a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
34610a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34620a708f8fSGustavo F. Padovan 
34630a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
34640a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
34650a708f8fSGustavo F. Padovan 
3466ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
34670a708f8fSGustavo F. Padovan 
34680a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
34690a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
34700a708f8fSGustavo F. Padovan 	}
34710a708f8fSGustavo F. Padovan 
3472c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
34730a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
34740a708f8fSGustavo F. Padovan 		u8 buf[128];
3475c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
34760a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
347773ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
347873ffa904SGustavo F. Padovan 		chan->num_conf_req++;
34790a708f8fSGustavo F. Padovan 	}
34800a708f8fSGustavo F. Padovan 
34810a708f8fSGustavo F. Padovan 	return 0;
34820a708f8fSGustavo F. Padovan }
34830a708f8fSGustavo F. Padovan 
34840a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34850a708f8fSGustavo F. Padovan {
34860a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
34870a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
348848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34890a708f8fSGustavo F. Padovan 	u8 req[128];
34903df91ea2SAndrei Emeltchenko 	int err;
34910a708f8fSGustavo F. Padovan 
34920a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
34930a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
34940a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
34950a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
34960a708f8fSGustavo F. Padovan 
34971b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
34981b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
34990a708f8fSGustavo F. Padovan 
35003df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
35013df91ea2SAndrei Emeltchenko 
35020a708f8fSGustavo F. Padovan 	if (scid) {
35033df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
35043df91ea2SAndrei Emeltchenko 		if (!chan) {
35053df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35063df91ea2SAndrei Emeltchenko 			goto unlock;
35073df91ea2SAndrei Emeltchenko 		}
35080a708f8fSGustavo F. Padovan 	} else {
35093df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
35103df91ea2SAndrei Emeltchenko 		if (!chan) {
35113df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35123df91ea2SAndrei Emeltchenko 			goto unlock;
35133df91ea2SAndrei Emeltchenko 		}
35140a708f8fSGustavo F. Padovan 	}
35150a708f8fSGustavo F. Padovan 
35163df91ea2SAndrei Emeltchenko 	err = 0;
35173df91ea2SAndrei Emeltchenko 
35186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
351948454079SGustavo F. Padovan 
35200a708f8fSGustavo F. Padovan 	switch (result) {
35210a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
352289bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3523fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3524fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3525c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
35260a708f8fSGustavo F. Padovan 
3527c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
35280a708f8fSGustavo F. Padovan 			break;
35290a708f8fSGustavo F. Padovan 
35300a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
353173ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
353273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
35330a708f8fSGustavo F. Padovan 		break;
35340a708f8fSGustavo F. Padovan 
35350a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3536c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
35370a708f8fSGustavo F. Padovan 		break;
35380a708f8fSGustavo F. Padovan 
35390a708f8fSGustavo F. Padovan 	default:
354048454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
35410a708f8fSGustavo F. Padovan 		break;
35420a708f8fSGustavo F. Padovan 	}
35430a708f8fSGustavo F. Padovan 
35446be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
35453df91ea2SAndrei Emeltchenko 
35463df91ea2SAndrei Emeltchenko unlock:
35473df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
35483df91ea2SAndrei Emeltchenko 
35493df91ea2SAndrei Emeltchenko 	return err;
35500a708f8fSGustavo F. Padovan }
35510a708f8fSGustavo F. Padovan 
355247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
35530a708f8fSGustavo F. Padovan {
35540a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
35550a708f8fSGustavo F. Padovan 	 * sides request it.
35560a708f8fSGustavo F. Padovan 	 */
35570c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
355847d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3559c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
356047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
35610a708f8fSGustavo F. Padovan }
35620a708f8fSGustavo F. Padovan 
35630a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
35640a708f8fSGustavo F. Padovan {
35650a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
35660a708f8fSGustavo F. Padovan 	u16 dcid, flags;
35670a708f8fSGustavo F. Padovan 	u8 rsp[64];
356848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35693c588192SMat Martineau 	int len, err = 0;
35700a708f8fSGustavo F. Padovan 
35710a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
35720a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
35730a708f8fSGustavo F. Padovan 
35740a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
35750a708f8fSGustavo F. Padovan 
3576baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
357748454079SGustavo F. Padovan 	if (!chan)
35780a708f8fSGustavo F. Padovan 		return -ENOENT;
35790a708f8fSGustavo F. Padovan 
3580033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3581e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
35820a708f8fSGustavo F. Padovan 
3583e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3584e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3585e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3586e2fd318eSIlia Kolomisnky 
35870a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
35880a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
35890a708f8fSGustavo F. Padovan 		goto unlock;
35900a708f8fSGustavo F. Padovan 	}
35910a708f8fSGustavo F. Padovan 
35920a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
35930a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
35947ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
35950a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3596fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
35970a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
35980a708f8fSGustavo F. Padovan 		goto unlock;
35990a708f8fSGustavo F. Padovan 	}
36000a708f8fSGustavo F. Padovan 
36010a708f8fSGustavo F. Padovan 	/* Store config. */
360273ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
360373ffa904SGustavo F. Padovan 	chan->conf_len += len;
36040a708f8fSGustavo F. Padovan 
36050a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
36060a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
36070a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3608fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36090a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
36100a708f8fSGustavo F. Padovan 		goto unlock;
36110a708f8fSGustavo F. Padovan 	}
36120a708f8fSGustavo F. Padovan 
36130a708f8fSGustavo F. Padovan 	/* Complete config. */
361473ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
36150a708f8fSGustavo F. Padovan 	if (len < 0) {
3616e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
36170a708f8fSGustavo F. Padovan 		goto unlock;
36180a708f8fSGustavo F. Padovan 	}
36190a708f8fSGustavo F. Padovan 
36200a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
362173ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
36220a708f8fSGustavo F. Padovan 
36230a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
362473ffa904SGustavo F. Padovan 	chan->conf_len = 0;
36250a708f8fSGustavo F. Padovan 
3626c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
36270a708f8fSGustavo F. Padovan 		goto unlock;
36280a708f8fSGustavo F. Padovan 
3629c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
363047d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
36310a708f8fSGustavo F. Padovan 
363289bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
36330a708f8fSGustavo F. Padovan 
3634105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3635105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
36363c588192SMat Martineau 			err = l2cap_ertm_init(chan);
36370a708f8fSGustavo F. Padovan 
36383c588192SMat Martineau 		if (err < 0)
36393c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
36403c588192SMat Martineau 		else
3641cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
36423c588192SMat Martineau 
36430a708f8fSGustavo F. Padovan 		goto unlock;
36440a708f8fSGustavo F. Padovan 	}
36450a708f8fSGustavo F. Padovan 
3646c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
36470a708f8fSGustavo F. Padovan 		u8 buf[64];
36480a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
364973ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
365073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
36510a708f8fSGustavo F. Padovan 	}
36520a708f8fSGustavo F. Padovan 
36530e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
36540e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
36550e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
36560e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
36570e8b207eSAndrei Emeltchenko 
36580e8b207eSAndrei Emeltchenko 		/* check compatibility */
36590e8b207eSAndrei Emeltchenko 
36600e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
36610e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
36620e8b207eSAndrei Emeltchenko 
36630e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
36640e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
36650e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
36660e8b207eSAndrei Emeltchenko 	}
36670e8b207eSAndrei Emeltchenko 
36680a708f8fSGustavo F. Padovan unlock:
36696be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36703c588192SMat Martineau 	return err;
36710a708f8fSGustavo F. Padovan }
36720a708f8fSGustavo F. Padovan 
36730a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36740a708f8fSGustavo F. Padovan {
36750a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
36760a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
367748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
367861386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
36793c588192SMat Martineau 	int err = 0;
36800a708f8fSGustavo F. Padovan 
36810a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
36820a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
36830a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
36840a708f8fSGustavo F. Padovan 
368561386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
368661386cbaSAndrei Emeltchenko 	       result, len);
36870a708f8fSGustavo F. Padovan 
3688baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
368948454079SGustavo F. Padovan 	if (!chan)
36900a708f8fSGustavo F. Padovan 		return 0;
36910a708f8fSGustavo F. Padovan 
36920a708f8fSGustavo F. Padovan 	switch (result) {
36930a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
369447d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
36950e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
36960a708f8fSGustavo F. Padovan 		break;
36970a708f8fSGustavo F. Padovan 
36980e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
36990e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
37000e8b207eSAndrei Emeltchenko 
37010e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
37020e8b207eSAndrei Emeltchenko 			char buf[64];
37030e8b207eSAndrei Emeltchenko 
37040e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
37050e8b207eSAndrei Emeltchenko 								buf, &result);
37060e8b207eSAndrei Emeltchenko 			if (len < 0) {
37070e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37080e8b207eSAndrei Emeltchenko 				goto done;
37090e8b207eSAndrei Emeltchenko 			}
37100e8b207eSAndrei Emeltchenko 
37110e8b207eSAndrei Emeltchenko 			/* check compatibility */
37120e8b207eSAndrei Emeltchenko 
37130e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
37140e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37150e8b207eSAndrei Emeltchenko 
37160e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
37170e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
37180e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
37190e8b207eSAndrei Emeltchenko 		}
37200e8b207eSAndrei Emeltchenko 		goto done;
37210e8b207eSAndrei Emeltchenko 
37220a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
372373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
37240a708f8fSGustavo F. Padovan 			char req[64];
37250a708f8fSGustavo F. Padovan 
37260a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3727e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37280a708f8fSGustavo F. Padovan 				goto done;
37290a708f8fSGustavo F. Padovan 			}
37300a708f8fSGustavo F. Padovan 
37310a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
37320a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3733b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3734b4450035SGustavo F. Padovan 								req, &result);
37350a708f8fSGustavo F. Padovan 			if (len < 0) {
3736e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37370a708f8fSGustavo F. Padovan 				goto done;
37380a708f8fSGustavo F. Padovan 			}
37390a708f8fSGustavo F. Padovan 
37400a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
37410a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
374273ffa904SGustavo F. Padovan 			chan->num_conf_req++;
37430a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
37440a708f8fSGustavo F. Padovan 				goto done;
37450a708f8fSGustavo F. Padovan 			break;
37460a708f8fSGustavo F. Padovan 		}
37470a708f8fSGustavo F. Padovan 
37480a708f8fSGustavo F. Padovan 	default:
37496be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
37502e0052e4SAndrei Emeltchenko 
3751ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3752e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
37530a708f8fSGustavo F. Padovan 		goto done;
37540a708f8fSGustavo F. Padovan 	}
37550a708f8fSGustavo F. Padovan 
37560a708f8fSGustavo F. Padovan 	if (flags & 0x01)
37570a708f8fSGustavo F. Padovan 		goto done;
37580a708f8fSGustavo F. Padovan 
3759c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
37600a708f8fSGustavo F. Padovan 
3761c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
376247d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
37630a708f8fSGustavo F. Padovan 
376489bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3765105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3766105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
37673c588192SMat Martineau 			err = l2cap_ertm_init(chan);
37680a708f8fSGustavo F. Padovan 
37693c588192SMat Martineau 		if (err < 0)
37703c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
37713c588192SMat Martineau 		else
3772cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
37730a708f8fSGustavo F. Padovan 	}
37740a708f8fSGustavo F. Padovan 
37750a708f8fSGustavo F. Padovan done:
37766be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
37773c588192SMat Martineau 	return err;
37780a708f8fSGustavo F. Padovan }
37790a708f8fSGustavo F. Padovan 
37800a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
37810a708f8fSGustavo F. Padovan {
37820a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
37830a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
37840a708f8fSGustavo F. Padovan 	u16 dcid, scid;
378548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
37860a708f8fSGustavo F. Padovan 	struct sock *sk;
37870a708f8fSGustavo F. Padovan 
37880a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
37890a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
37900a708f8fSGustavo F. Padovan 
37910a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
37920a708f8fSGustavo F. Padovan 
37933df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
37943df91ea2SAndrei Emeltchenko 
37953df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
37963df91ea2SAndrei Emeltchenko 	if (!chan) {
37973df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
37980a708f8fSGustavo F. Padovan 		return 0;
37993df91ea2SAndrei Emeltchenko 	}
38000a708f8fSGustavo F. Padovan 
38016be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
38026be36555SAndrei Emeltchenko 
380348454079SGustavo F. Padovan 	sk = chan->sk;
380448454079SGustavo F. Padovan 
3805fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3806fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
38070a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
38080a708f8fSGustavo F. Padovan 
38096be36555SAndrei Emeltchenko 	lock_sock(sk);
38100a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
38116be36555SAndrei Emeltchenko 	release_sock(sk);
38120a708f8fSGustavo F. Padovan 
381361d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
381448454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
38156be36555SAndrei Emeltchenko 
38166be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38170a708f8fSGustavo F. Padovan 
3818ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
381961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38203df91ea2SAndrei Emeltchenko 
38213df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38223df91ea2SAndrei Emeltchenko 
38230a708f8fSGustavo F. Padovan 	return 0;
38240a708f8fSGustavo F. Padovan }
38250a708f8fSGustavo F. Padovan 
38260a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38270a708f8fSGustavo F. Padovan {
38280a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
38290a708f8fSGustavo F. Padovan 	u16 dcid, scid;
383048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38310a708f8fSGustavo F. Padovan 
38320a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
38330a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
38340a708f8fSGustavo F. Padovan 
38350a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
38360a708f8fSGustavo F. Padovan 
38373df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38383df91ea2SAndrei Emeltchenko 
38393df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
38403df91ea2SAndrei Emeltchenko 	if (!chan) {
38413df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38420a708f8fSGustavo F. Padovan 		return 0;
38433df91ea2SAndrei Emeltchenko 	}
38440a708f8fSGustavo F. Padovan 
38456be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
384648454079SGustavo F. Padovan 
384761d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
384848454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
38496be36555SAndrei Emeltchenko 
38506be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38510a708f8fSGustavo F. Padovan 
3852ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
385361d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38543df91ea2SAndrei Emeltchenko 
38553df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38563df91ea2SAndrei Emeltchenko 
38570a708f8fSGustavo F. Padovan 	return 0;
38580a708f8fSGustavo F. Padovan }
38590a708f8fSGustavo F. Padovan 
38600a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38610a708f8fSGustavo F. Padovan {
38620a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
38630a708f8fSGustavo F. Padovan 	u16 type;
38640a708f8fSGustavo F. Padovan 
38650a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
38660a708f8fSGustavo F. Padovan 
38670a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
38680a708f8fSGustavo F. Padovan 
38690a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
38700a708f8fSGustavo F. Padovan 		u8 buf[8];
38710a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
38720a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
38730a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
38740a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
38750a708f8fSGustavo F. Padovan 		if (!disable_ertm)
38760a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
38770a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3878a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
38796327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
38806327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3881a5fd6f30SAndrei Emeltchenko 
38820a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
38830a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
38840a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
38850a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
38860a708f8fSGustavo F. Padovan 		u8 buf[12];
38870a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
388850a147cdSMat Martineau 
388950a147cdSMat Martineau 		if (enable_hs)
389050a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
389150a147cdSMat Martineau 		else
389250a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
389350a147cdSMat Martineau 
38940a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
38950a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3896c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
38970a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
38980a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
38990a708f8fSGustavo F. Padovan 	} else {
39000a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
39010a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
39020a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
39030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39040a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
39050a708f8fSGustavo F. Padovan 	}
39060a708f8fSGustavo F. Padovan 
39070a708f8fSGustavo F. Padovan 	return 0;
39080a708f8fSGustavo F. Padovan }
39090a708f8fSGustavo F. Padovan 
39100a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
39110a708f8fSGustavo F. Padovan {
39120a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
39130a708f8fSGustavo F. Padovan 	u16 type, result;
39140a708f8fSGustavo F. Padovan 
39150a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
39160a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
39170a708f8fSGustavo F. Padovan 
39180a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
39190a708f8fSGustavo F. Padovan 
3920e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3921e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3922e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3923e90165beSAndrei Emeltchenko 		return 0;
3924e90165beSAndrei Emeltchenko 
392517cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
39260a708f8fSGustavo F. Padovan 
39270a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
39280a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39290a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39300a708f8fSGustavo F. Padovan 
39310a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39320a708f8fSGustavo F. Padovan 
39330a708f8fSGustavo F. Padovan 		return 0;
39340a708f8fSGustavo F. Padovan 	}
39350a708f8fSGustavo F. Padovan 
3936978c93b9SAndrei Emeltchenko 	switch (type) {
3937978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
39380a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
39390a708f8fSGustavo F. Padovan 
39400a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
39410a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
39420a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39430a708f8fSGustavo F. Padovan 
39440a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
39450a708f8fSGustavo F. Padovan 
39460a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
39470a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
39480a708f8fSGustavo F. Padovan 		} else {
39490a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39500a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
39510a708f8fSGustavo F. Padovan 
39520a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
39530a708f8fSGustavo F. Padovan 		}
3954978c93b9SAndrei Emeltchenko 		break;
3955978c93b9SAndrei Emeltchenko 
3956978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3957978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
39580a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39590a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39600a708f8fSGustavo F. Padovan 
39610a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3962978c93b9SAndrei Emeltchenko 		break;
39630a708f8fSGustavo F. Padovan 	}
39640a708f8fSGustavo F. Padovan 
39650a708f8fSGustavo F. Padovan 	return 0;
39660a708f8fSGustavo F. Padovan }
39670a708f8fSGustavo F. Padovan 
3968f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3969f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3970f94ff6ffSMat Martineau 					void *data)
3971f94ff6ffSMat Martineau {
3972f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3973f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3974f94ff6ffSMat Martineau 	u16 psm, scid;
3975f94ff6ffSMat Martineau 
3976f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3977f94ff6ffSMat Martineau 		return -EPROTO;
3978f94ff6ffSMat Martineau 
3979f94ff6ffSMat Martineau 	if (!enable_hs)
3980f94ff6ffSMat Martineau 		return -EINVAL;
3981f94ff6ffSMat Martineau 
3982f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3983f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3984f94ff6ffSMat Martineau 
3985f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3986f94ff6ffSMat Martineau 
3987f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3988f94ff6ffSMat Martineau 	rsp.dcid = 0;
3989f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
39908ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
39918ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3992f94ff6ffSMat Martineau 
3993f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3994f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3995f94ff6ffSMat Martineau 
3996f94ff6ffSMat Martineau 	return 0;
3997f94ff6ffSMat Martineau }
3998f94ff6ffSMat Martineau 
3999f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
4000f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
4001f94ff6ffSMat Martineau {
4002f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
4003f94ff6ffSMat Martineau 
4004f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
4005f94ff6ffSMat Martineau }
4006f94ff6ffSMat Martineau 
40078d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
40088d5a04a1SMat Martineau 							u16 icid, u16 result)
40098d5a04a1SMat Martineau {
40108d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
40118d5a04a1SMat Martineau 
40128d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40138d5a04a1SMat Martineau 
40148d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40158d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
40168d5a04a1SMat Martineau 
40178d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
40188d5a04a1SMat Martineau }
40198d5a04a1SMat Martineau 
40208d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
40218d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
40228d5a04a1SMat Martineau {
40238d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
40248d5a04a1SMat Martineau 	u8 ident;
40258d5a04a1SMat Martineau 
40268d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40278d5a04a1SMat Martineau 
40288d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
40298d5a04a1SMat Martineau 	if (chan)
40308d5a04a1SMat Martineau 		chan->ident = ident;
40318d5a04a1SMat Martineau 
40328d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
40338d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
40348d5a04a1SMat Martineau 
40358d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
40368d5a04a1SMat Martineau }
40378d5a04a1SMat Martineau 
40388d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
40398d5a04a1SMat Martineau 								u16 icid)
40408d5a04a1SMat Martineau {
40418d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
40428d5a04a1SMat Martineau 
40438d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
40448d5a04a1SMat Martineau 
40458d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40468d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
40478d5a04a1SMat Martineau }
40488d5a04a1SMat Martineau 
40498d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
40508d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40518d5a04a1SMat Martineau {
40528d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
40538d5a04a1SMat Martineau 	u16 icid = 0;
40548d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
40558d5a04a1SMat Martineau 
40568d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
40578d5a04a1SMat Martineau 		return -EPROTO;
40588d5a04a1SMat Martineau 
40598d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
40608d5a04a1SMat Martineau 
40618d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
40628d5a04a1SMat Martineau 
40638d5a04a1SMat Martineau 	if (!enable_hs)
40648d5a04a1SMat Martineau 		return -EINVAL;
40658d5a04a1SMat Martineau 
40668d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
40678d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
40688d5a04a1SMat Martineau 
40698d5a04a1SMat Martineau 	return 0;
40708d5a04a1SMat Martineau }
40718d5a04a1SMat Martineau 
40728d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
40738d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40748d5a04a1SMat Martineau {
40758d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
40768d5a04a1SMat Martineau 	u16 icid, result;
40778d5a04a1SMat Martineau 
40788d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
40798d5a04a1SMat Martineau 		return -EPROTO;
40808d5a04a1SMat Martineau 
40818d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
40828d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
40838d5a04a1SMat Martineau 
40848d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40858d5a04a1SMat Martineau 
40868d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
40878d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
40888d5a04a1SMat Martineau 
40898d5a04a1SMat Martineau 	return 0;
40908d5a04a1SMat Martineau }
40918d5a04a1SMat Martineau 
40928d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
40938d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40948d5a04a1SMat Martineau {
40958d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
40968d5a04a1SMat Martineau 	u16 icid, result;
40978d5a04a1SMat Martineau 
40988d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
40998d5a04a1SMat Martineau 		return -EPROTO;
41008d5a04a1SMat Martineau 
41018d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
41028d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
41038d5a04a1SMat Martineau 
41048d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
41058d5a04a1SMat Martineau 
41068d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
41078d5a04a1SMat Martineau 
41088d5a04a1SMat Martineau 	return 0;
41098d5a04a1SMat Martineau }
41108d5a04a1SMat Martineau 
41118d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
41128d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
41138d5a04a1SMat Martineau {
41148d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
41158d5a04a1SMat Martineau 	u16 icid;
41168d5a04a1SMat Martineau 
41178d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
41188d5a04a1SMat Martineau 		return -EPROTO;
41198d5a04a1SMat Martineau 
41208d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
41218d5a04a1SMat Martineau 
41228d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
41238d5a04a1SMat Martineau 
41248d5a04a1SMat Martineau 	return 0;
41258d5a04a1SMat Martineau }
41268d5a04a1SMat Martineau 
4127e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
4128de73115aSClaudio Takahasi 							u16 to_multiplier)
4129de73115aSClaudio Takahasi {
4130de73115aSClaudio Takahasi 	u16 max_latency;
4131de73115aSClaudio Takahasi 
4132de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
4133de73115aSClaudio Takahasi 		return -EINVAL;
4134de73115aSClaudio Takahasi 
4135de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
4136de73115aSClaudio Takahasi 		return -EINVAL;
4137de73115aSClaudio Takahasi 
4138de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
4139de73115aSClaudio Takahasi 		return -EINVAL;
4140de73115aSClaudio Takahasi 
4141de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
4142de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
4143de73115aSClaudio Takahasi 		return -EINVAL;
4144de73115aSClaudio Takahasi 
4145de73115aSClaudio Takahasi 	return 0;
4146de73115aSClaudio Takahasi }
4147de73115aSClaudio Takahasi 
4148de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
4149de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
4150de73115aSClaudio Takahasi {
4151de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
4152de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
4153de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
4154de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
41552ce603ebSClaudio Takahasi 	int err;
4156de73115aSClaudio Takahasi 
4157de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
4158de73115aSClaudio Takahasi 		return -EINVAL;
4159de73115aSClaudio Takahasi 
4160de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
4161de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4162de73115aSClaudio Takahasi 		return -EPROTO;
4163de73115aSClaudio Takahasi 
4164de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4165de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4166de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4167de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4168de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4169de73115aSClaudio Takahasi 
4170de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4171de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
4172de73115aSClaudio Takahasi 
4173de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
41742ce603ebSClaudio Takahasi 
41752ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
41762ce603ebSClaudio Takahasi 	if (err)
4177de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4178de73115aSClaudio Takahasi 	else
4179de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4180de73115aSClaudio Takahasi 
4181de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4182de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
4183de73115aSClaudio Takahasi 
41842ce603ebSClaudio Takahasi 	if (!err)
41852ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
41862ce603ebSClaudio Takahasi 
4187de73115aSClaudio Takahasi 	return 0;
4188de73115aSClaudio Takahasi }
4189de73115aSClaudio Takahasi 
41903300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
41913300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
41923300d9a9SClaudio Takahasi {
41933300d9a9SClaudio Takahasi 	int err = 0;
41943300d9a9SClaudio Takahasi 
41953300d9a9SClaudio Takahasi 	switch (cmd->code) {
41963300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
41973300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
41983300d9a9SClaudio Takahasi 		break;
41993300d9a9SClaudio Takahasi 
42003300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
42013300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
42023300d9a9SClaudio Takahasi 		break;
42033300d9a9SClaudio Takahasi 
42043300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
42053300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
42063300d9a9SClaudio Takahasi 		break;
42073300d9a9SClaudio Takahasi 
42083300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
42093300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
42103300d9a9SClaudio Takahasi 		break;
42113300d9a9SClaudio Takahasi 
42123300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
42133300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
42143300d9a9SClaudio Takahasi 		break;
42153300d9a9SClaudio Takahasi 
42163300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
42173300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
42183300d9a9SClaudio Takahasi 		break;
42193300d9a9SClaudio Takahasi 
42203300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
42213300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
42223300d9a9SClaudio Takahasi 		break;
42233300d9a9SClaudio Takahasi 
42243300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
42253300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
42263300d9a9SClaudio Takahasi 		break;
42273300d9a9SClaudio Takahasi 
42283300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
42293300d9a9SClaudio Takahasi 		break;
42303300d9a9SClaudio Takahasi 
42313300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
42323300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
42333300d9a9SClaudio Takahasi 		break;
42343300d9a9SClaudio Takahasi 
42353300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
42363300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
42373300d9a9SClaudio Takahasi 		break;
42383300d9a9SClaudio Takahasi 
4239f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
4240f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4241f94ff6ffSMat Martineau 		break;
4242f94ff6ffSMat Martineau 
4243f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
4244f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
4245f94ff6ffSMat Martineau 		break;
4246f94ff6ffSMat Martineau 
42478d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
42488d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
42498d5a04a1SMat Martineau 		break;
42508d5a04a1SMat Martineau 
42518d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
42528d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
42538d5a04a1SMat Martineau 		break;
42548d5a04a1SMat Martineau 
42558d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
42568d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
42578d5a04a1SMat Martineau 		break;
42588d5a04a1SMat Martineau 
42598d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
42608d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
42618d5a04a1SMat Martineau 		break;
42628d5a04a1SMat Martineau 
42633300d9a9SClaudio Takahasi 	default:
42643300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
42653300d9a9SClaudio Takahasi 		err = -EINVAL;
42663300d9a9SClaudio Takahasi 		break;
42673300d9a9SClaudio Takahasi 	}
42683300d9a9SClaudio Takahasi 
42693300d9a9SClaudio Takahasi 	return err;
42703300d9a9SClaudio Takahasi }
42713300d9a9SClaudio Takahasi 
42723300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
42733300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
42743300d9a9SClaudio Takahasi {
42753300d9a9SClaudio Takahasi 	switch (cmd->code) {
42763300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
42773300d9a9SClaudio Takahasi 		return 0;
42783300d9a9SClaudio Takahasi 
42793300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
4280de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
42813300d9a9SClaudio Takahasi 
42823300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
42833300d9a9SClaudio Takahasi 		return 0;
42843300d9a9SClaudio Takahasi 
42853300d9a9SClaudio Takahasi 	default:
42863300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
42873300d9a9SClaudio Takahasi 		return -EINVAL;
42883300d9a9SClaudio Takahasi 	}
42893300d9a9SClaudio Takahasi }
42903300d9a9SClaudio Takahasi 
42913300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
42923300d9a9SClaudio Takahasi 							struct sk_buff *skb)
42930a708f8fSGustavo F. Padovan {
42940a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
42950a708f8fSGustavo F. Padovan 	int len = skb->len;
42960a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
42973300d9a9SClaudio Takahasi 	int err;
42980a708f8fSGustavo F. Padovan 
42990a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
43000a708f8fSGustavo F. Padovan 
43010a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
43020a708f8fSGustavo F. Padovan 		u16 cmd_len;
43030a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
43040a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
43050a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
43060a708f8fSGustavo F. Padovan 
43070a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
43080a708f8fSGustavo F. Padovan 
43090a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
43100a708f8fSGustavo F. Padovan 
43110a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
43120a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
43130a708f8fSGustavo F. Padovan 			break;
43140a708f8fSGustavo F. Padovan 		}
43150a708f8fSGustavo F. Padovan 
43163300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
43173300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
43183300d9a9SClaudio Takahasi 		else
43193300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
43200a708f8fSGustavo F. Padovan 
43210a708f8fSGustavo F. Padovan 		if (err) {
4322e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
43232c6d1a2eSGustavo F. Padovan 
43242c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
43250a708f8fSGustavo F. Padovan 
43260a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
4327e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
43280a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
43290a708f8fSGustavo F. Padovan 		}
43300a708f8fSGustavo F. Padovan 
43310a708f8fSGustavo F. Padovan 		data += cmd_len;
43320a708f8fSGustavo F. Padovan 		len  -= cmd_len;
43330a708f8fSGustavo F. Padovan 	}
43340a708f8fSGustavo F. Padovan 
43350a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43360a708f8fSGustavo F. Padovan }
43370a708f8fSGustavo F. Padovan 
433847d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
43390a708f8fSGustavo F. Padovan {
43400a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
4341e4ca6d98SAndrei Emeltchenko 	int hdr_size;
4342e4ca6d98SAndrei Emeltchenko 
4343e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4344e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
4345e4ca6d98SAndrei Emeltchenko 	else
4346e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
43470a708f8fSGustavo F. Padovan 
434847d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
434903a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
43500a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
43510a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
43520a708f8fSGustavo F. Padovan 
43530a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
43540a708f8fSGustavo F. Padovan 			return -EBADMSG;
43550a708f8fSGustavo F. Padovan 	}
43560a708f8fSGustavo F. Padovan 	return 0;
43570a708f8fSGustavo F. Padovan }
43580a708f8fSGustavo F. Padovan 
4359525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
43600a708f8fSGustavo F. Padovan {
4361e31f7633SMat Martineau 	struct l2cap_ctrl control;
43620a708f8fSGustavo F. Padovan 
4363e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
43640a708f8fSGustavo F. Padovan 
4365e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
4366e31f7633SMat Martineau 	control.sframe = 1;
4367e31f7633SMat Martineau 	control.final = 1;
4368e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
4369e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
43700a708f8fSGustavo F. Padovan 
4371e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4372e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
4373e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43740a708f8fSGustavo F. Padovan 	}
43750a708f8fSGustavo F. Padovan 
4376e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4377e31f7633SMat Martineau 	    chan->unacked_frames > 0)
4378e31f7633SMat Martineau 		__set_retrans_timer(chan);
43790a708f8fSGustavo F. Padovan 
4380e31f7633SMat Martineau 	/* Send pending iframes */
4381525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
43820a708f8fSGustavo F. Padovan 
4383e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4384e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4385e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
4386e31f7633SMat Martineau 		 * send it now.
4387e31f7633SMat Martineau 		 */
4388e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
4389e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43900a708f8fSGustavo F. Padovan 	}
43910a708f8fSGustavo F. Padovan }
43920a708f8fSGustavo F. Padovan 
439384084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
439484084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
43950a708f8fSGustavo F. Padovan {
439684084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
439784084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
439884084a31SMat Martineau 	 */
439984084a31SMat Martineau 	if (!skb_has_frag_list(skb))
440084084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
440184084a31SMat Martineau 
440284084a31SMat Martineau 	new_frag->next = NULL;
440384084a31SMat Martineau 
440484084a31SMat Martineau 	(*last_frag)->next = new_frag;
440584084a31SMat Martineau 	*last_frag = new_frag;
440684084a31SMat Martineau 
440784084a31SMat Martineau 	skb->len += new_frag->len;
440884084a31SMat Martineau 	skb->data_len += new_frag->len;
440984084a31SMat Martineau 	skb->truesize += new_frag->truesize;
441084084a31SMat Martineau }
441184084a31SMat Martineau 
44124b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
44134b51dae9SMat Martineau 				struct l2cap_ctrl *control)
441484084a31SMat Martineau {
441584084a31SMat Martineau 	int err = -EINVAL;
44160a708f8fSGustavo F. Padovan 
44174b51dae9SMat Martineau 	switch (control->sar) {
44187e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
441984084a31SMat Martineau 		if (chan->sdu)
442084084a31SMat Martineau 			break;
44210a708f8fSGustavo F. Padovan 
442284084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
442384084a31SMat Martineau 		break;
44240a708f8fSGustavo F. Padovan 
44257e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
442684084a31SMat Martineau 		if (chan->sdu)
442784084a31SMat Martineau 			break;
44280a708f8fSGustavo F. Padovan 
44296f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
443003a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
44310a708f8fSGustavo F. Padovan 
443284084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
443384084a31SMat Martineau 			err = -EMSGSIZE;
443484084a31SMat Martineau 			break;
443584084a31SMat Martineau 		}
44360a708f8fSGustavo F. Padovan 
443784084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
443884084a31SMat Martineau 			break;
443984084a31SMat Martineau 
444084084a31SMat Martineau 		chan->sdu = skb;
444184084a31SMat Martineau 		chan->sdu_last_frag = skb;
444284084a31SMat Martineau 
444384084a31SMat Martineau 		skb = NULL;
444484084a31SMat Martineau 		err = 0;
44450a708f8fSGustavo F. Padovan 		break;
44460a708f8fSGustavo F. Padovan 
44477e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
44486f61fd47SGustavo F. Padovan 		if (!chan->sdu)
444984084a31SMat Martineau 			break;
44500a708f8fSGustavo F. Padovan 
445184084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
445284084a31SMat Martineau 				&chan->sdu_last_frag);
445384084a31SMat Martineau 		skb = NULL;
44540a708f8fSGustavo F. Padovan 
445584084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
445684084a31SMat Martineau 			break;
44570a708f8fSGustavo F. Padovan 
445884084a31SMat Martineau 		err = 0;
44590a708f8fSGustavo F. Padovan 		break;
44600a708f8fSGustavo F. Padovan 
44617e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
44626f61fd47SGustavo F. Padovan 		if (!chan->sdu)
446384084a31SMat Martineau 			break;
44640a708f8fSGustavo F. Padovan 
446584084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
446684084a31SMat Martineau 				&chan->sdu_last_frag);
446784084a31SMat Martineau 		skb = NULL;
44680a708f8fSGustavo F. Padovan 
446984084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
447084084a31SMat Martineau 			break;
44710a708f8fSGustavo F. Padovan 
447284084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
44730a708f8fSGustavo F. Padovan 
447484084a31SMat Martineau 		if (!err) {
447584084a31SMat Martineau 			/* Reassembly complete */
447684084a31SMat Martineau 			chan->sdu = NULL;
447784084a31SMat Martineau 			chan->sdu_last_frag = NULL;
447884084a31SMat Martineau 			chan->sdu_len = 0;
44790a708f8fSGustavo F. Padovan 		}
44800a708f8fSGustavo F. Padovan 		break;
44810a708f8fSGustavo F. Padovan 	}
44820a708f8fSGustavo F. Padovan 
448384084a31SMat Martineau 	if (err) {
44840a708f8fSGustavo F. Padovan 		kfree_skb(skb);
44856f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
44866f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
448784084a31SMat Martineau 		chan->sdu_last_frag = NULL;
448884084a31SMat Martineau 		chan->sdu_len = 0;
448984084a31SMat Martineau 	}
44900a708f8fSGustavo F. Padovan 
449184084a31SMat Martineau 	return err;
44920a708f8fSGustavo F. Padovan }
44930a708f8fSGustavo F. Padovan 
4494e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
44950a708f8fSGustavo F. Padovan {
449661aa4f5bSMat Martineau 	u8 event;
449761aa4f5bSMat Martineau 
449861aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
449961aa4f5bSMat Martineau 		return;
450061aa4f5bSMat Martineau 
450161aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
450261aa4f5bSMat Martineau 	l2cap_tx(chan, 0, 0, event);
45030a708f8fSGustavo F. Padovan }
45040a708f8fSGustavo F. Padovan 
4505d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
4506d2a7ac5dSMat Martineau {
450763838725SMat Martineau 	int err = 0;
450863838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
450963838725SMat Martineau 	 * until a gap is encountered.
451063838725SMat Martineau 	 */
451163838725SMat Martineau 
451263838725SMat Martineau 	BT_DBG("chan %p", chan);
451363838725SMat Martineau 
451463838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
451563838725SMat Martineau 		struct sk_buff *skb;
451663838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
451763838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
451863838725SMat Martineau 
451963838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
452063838725SMat Martineau 
452163838725SMat Martineau 		if (!skb)
452263838725SMat Martineau 			break;
452363838725SMat Martineau 
452463838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
452563838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
452663838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
452763838725SMat Martineau 		if (err)
452863838725SMat Martineau 			break;
452963838725SMat Martineau 	}
453063838725SMat Martineau 
453163838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
453263838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
453363838725SMat Martineau 		l2cap_send_ack(chan);
453463838725SMat Martineau 	}
453563838725SMat Martineau 
453663838725SMat Martineau 	return err;
4537d2a7ac5dSMat Martineau }
4538d2a7ac5dSMat Martineau 
4539d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
4540d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
4541d2a7ac5dSMat Martineau {
4542d2a7ac5dSMat Martineau 	/* Placeholder */
4543d2a7ac5dSMat Martineau }
4544d2a7ac5dSMat Martineau 
4545d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
4546d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
4547d2a7ac5dSMat Martineau {
4548d2a7ac5dSMat Martineau 	/* Placeholder */
4549d2a7ac5dSMat Martineau }
4550d2a7ac5dSMat Martineau 
45514b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
45524b51dae9SMat Martineau {
45534b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
45544b51dae9SMat Martineau 
45554b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
45564b51dae9SMat Martineau 	       chan->expected_tx_seq);
45574b51dae9SMat Martineau 
45584b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
45594b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
45604b51dae9SMat Martineau 								chan->tx_win) {
45614b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
45624b51dae9SMat Martineau 			 * invalid packets.
45634b51dae9SMat Martineau 			 */
45644b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
45654b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
45664b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
45674b51dae9SMat Martineau 			} else {
45684b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
45694b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
45704b51dae9SMat Martineau 			}
45714b51dae9SMat Martineau 		}
45724b51dae9SMat Martineau 
45734b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
45744b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
45754b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
45764b51dae9SMat Martineau 		}
45774b51dae9SMat Martineau 
45784b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
45794b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
45804b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
45814b51dae9SMat Martineau 		}
45824b51dae9SMat Martineau 
45834b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
45844b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
45854b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
45864b51dae9SMat Martineau 		}
45874b51dae9SMat Martineau 	}
45884b51dae9SMat Martineau 
45894b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
45904b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
45914b51dae9SMat Martineau 		    chan->tx_win) {
45924b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
45934b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
45944b51dae9SMat Martineau 		} else {
45954b51dae9SMat Martineau 			BT_DBG("Expected");
45964b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
45974b51dae9SMat Martineau 		}
45984b51dae9SMat Martineau 	}
45994b51dae9SMat Martineau 
46004b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
46014b51dae9SMat Martineau 		__seq_offset(chan, chan->expected_tx_seq,
46024b51dae9SMat Martineau 			     chan->last_acked_seq)){
46034b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
46044b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
46054b51dae9SMat Martineau 	}
46064b51dae9SMat Martineau 
46074b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
46084b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
46094b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
46104b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
46114b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
46124b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
46134b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
46144b51dae9SMat Martineau 		 * request.
46154b51dae9SMat Martineau 		 *
46164b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
46174b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
46184b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
46194b51dae9SMat Martineau 		 *
46204b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
46214b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
46224b51dae9SMat Martineau 		 * causes a disconnect.
46234b51dae9SMat Martineau 		 */
46244b51dae9SMat Martineau 
46254b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
46264b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
46274b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
46284b51dae9SMat Martineau 		} else {
46294b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
46304b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
46314b51dae9SMat Martineau 		}
46324b51dae9SMat Martineau 	} else {
46334b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
46344b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
46354b51dae9SMat Martineau 	}
46364b51dae9SMat Martineau }
46374b51dae9SMat Martineau 
4638d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
4639d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
4640d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
4641d2a7ac5dSMat Martineau {
4642d2a7ac5dSMat Martineau 	int err = 0;
4643d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4644d2a7ac5dSMat Martineau 
4645d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4646d2a7ac5dSMat Martineau 	       event);
4647d2a7ac5dSMat Martineau 
4648d2a7ac5dSMat Martineau 	switch (event) {
4649d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4650d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
4651d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4652d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4653d2a7ac5dSMat Martineau 
4654d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4655d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
4656d2a7ac5dSMat Martineau 				       control->txseq);
4657d2a7ac5dSMat Martineau 				break;
4658d2a7ac5dSMat Martineau 			}
4659d2a7ac5dSMat Martineau 
4660d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
4661d2a7ac5dSMat Martineau 							   control->txseq);
4662d2a7ac5dSMat Martineau 
4663d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
4664d2a7ac5dSMat Martineau 			skb_in_use = 1;
4665d2a7ac5dSMat Martineau 
4666d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
4667d2a7ac5dSMat Martineau 			if (err)
4668d2a7ac5dSMat Martineau 				break;
4669d2a7ac5dSMat Martineau 
4670d2a7ac5dSMat Martineau 			if (control->final) {
4671d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
4672d2a7ac5dSMat Martineau 							&chan->conn_state)) {
4673d2a7ac5dSMat Martineau 					control->final = 0;
4674d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
4675d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
4676d2a7ac5dSMat Martineau 				}
4677d2a7ac5dSMat Martineau 			}
4678d2a7ac5dSMat Martineau 
4679d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
4680d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
4681d2a7ac5dSMat Martineau 			break;
4682d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4683d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4684d2a7ac5dSMat Martineau 
4685d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
4686d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
4687d2a7ac5dSMat Martineau 			 * when local busy is exited.
4688d2a7ac5dSMat Martineau 			 */
4689d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4690d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
4691d2a7ac5dSMat Martineau 				       control->txseq);
4692d2a7ac5dSMat Martineau 				break;
4693d2a7ac5dSMat Martineau 			}
4694d2a7ac5dSMat Martineau 
4695d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
4696d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
4697d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
4698d2a7ac5dSMat Martineau 			 */
4699d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4700d2a7ac5dSMat Martineau 			skb_in_use = 1;
4701d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4702d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4703d2a7ac5dSMat Martineau 
4704d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
4705d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
4706d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4707d2a7ac5dSMat Martineau 
4708d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
4709d2a7ac5dSMat Martineau 			break;
4710d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4711d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4712d2a7ac5dSMat Martineau 			break;
4713d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4714d2a7ac5dSMat Martineau 			break;
4715d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4716d2a7ac5dSMat Martineau 		default:
4717d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4718d2a7ac5dSMat Martineau 					       ECONNRESET);
4719d2a7ac5dSMat Martineau 			break;
4720d2a7ac5dSMat Martineau 		}
4721d2a7ac5dSMat Martineau 		break;
4722d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4723d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4724d2a7ac5dSMat Martineau 		if (control->final) {
4725d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4726d2a7ac5dSMat Martineau 
4727d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4728d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4729d2a7ac5dSMat Martineau 				control->final = 0;
4730d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4731d2a7ac5dSMat Martineau 			}
4732d2a7ac5dSMat Martineau 
4733d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4734d2a7ac5dSMat Martineau 		} else if (control->poll) {
4735d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
4736d2a7ac5dSMat Martineau 		} else {
4737d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4738d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4739d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4740d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4741d2a7ac5dSMat Martineau 
4742d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4743d2a7ac5dSMat Martineau 		}
4744d2a7ac5dSMat Martineau 		break;
4745d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4746d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4747d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4748d2a7ac5dSMat Martineau 		if (control && control->poll) {
4749d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4750d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
4751d2a7ac5dSMat Martineau 		}
4752d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
4753d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
4754d2a7ac5dSMat Martineau 		break;
4755d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4756d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4757d2a7ac5dSMat Martineau 		break;
4758d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4759d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4760d2a7ac5dSMat Martineau 		break;
4761d2a7ac5dSMat Martineau 	default:
4762d2a7ac5dSMat Martineau 		break;
4763d2a7ac5dSMat Martineau 	}
4764d2a7ac5dSMat Martineau 
4765d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4766d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4767d2a7ac5dSMat Martineau 		kfree_skb(skb);
4768d2a7ac5dSMat Martineau 	}
4769d2a7ac5dSMat Martineau 
4770d2a7ac5dSMat Martineau 	return err;
4771d2a7ac5dSMat Martineau }
4772d2a7ac5dSMat Martineau 
4773d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
4774d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
4775d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
4776d2a7ac5dSMat Martineau {
4777d2a7ac5dSMat Martineau 	int err = 0;
4778d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
4779d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4780d2a7ac5dSMat Martineau 
4781d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4782d2a7ac5dSMat Martineau 	       event);
4783d2a7ac5dSMat Martineau 
4784d2a7ac5dSMat Martineau 	switch (event) {
4785d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4786d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
4787d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4788d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
4789d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4790d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4791d2a7ac5dSMat Martineau 			skb_in_use = 1;
4792d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4793d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4794d2a7ac5dSMat Martineau 
4795d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
4796d2a7ac5dSMat Martineau 			break;
4797d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
4798d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
4799d2a7ac5dSMat Martineau 
4800d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4801d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4802d2a7ac5dSMat Martineau 			skb_in_use = 1;
4803d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4804d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4805d2a7ac5dSMat Martineau 
4806d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
4807d2a7ac5dSMat Martineau 			if (err)
4808d2a7ac5dSMat Martineau 				break;
4809d2a7ac5dSMat Martineau 
4810d2a7ac5dSMat Martineau 			break;
4811d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4812d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
4813d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
4814d2a7ac5dSMat Martineau 			 * the missing frames.
4815d2a7ac5dSMat Martineau 			 */
4816d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4817d2a7ac5dSMat Martineau 			skb_in_use = 1;
4818d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4819d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4820d2a7ac5dSMat Martineau 
4821d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4822d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4823d2a7ac5dSMat Martineau 			break;
4824d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
4825d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
4826d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
4827d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
4828d2a7ac5dSMat Martineau 			 * SREJ'd frames.
4829d2a7ac5dSMat Martineau 			 */
4830d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4831d2a7ac5dSMat Martineau 			skb_in_use = 1;
4832d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4833d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4834d2a7ac5dSMat Martineau 
4835d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4836d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
4837d2a7ac5dSMat Martineau 			break;
4838d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
4839d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
4840d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4841d2a7ac5dSMat Martineau 			break;
4842d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4843d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
4844d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
4845d2a7ac5dSMat Martineau 			 */
4846d2a7ac5dSMat Martineau 			break;
4847d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4848d2a7ac5dSMat Martineau 			break;
4849d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4850d2a7ac5dSMat Martineau 		default:
4851d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4852d2a7ac5dSMat Martineau 					       ECONNRESET);
4853d2a7ac5dSMat Martineau 			break;
4854d2a7ac5dSMat Martineau 		}
4855d2a7ac5dSMat Martineau 		break;
4856d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4857d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4858d2a7ac5dSMat Martineau 		if (control->final) {
4859d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4860d2a7ac5dSMat Martineau 
4861d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4862d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4863d2a7ac5dSMat Martineau 				control->final = 0;
4864d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4865d2a7ac5dSMat Martineau 			}
4866d2a7ac5dSMat Martineau 
4867d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4868d2a7ac5dSMat Martineau 		} else if (control->poll) {
4869d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4870d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4871d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
4872d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4873d2a7ac5dSMat Martineau 			}
4874d2a7ac5dSMat Martineau 
4875d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4876d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4877d2a7ac5dSMat Martineau 		} else {
4878d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4879d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4880d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4881d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4882d2a7ac5dSMat Martineau 
4883d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
4884d2a7ac5dSMat Martineau 		}
4885d2a7ac5dSMat Martineau 		break;
4886d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4887d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4888d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4889d2a7ac5dSMat Martineau 		if (control->poll) {
4890d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4891d2a7ac5dSMat Martineau 		} else {
4892d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
4893d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
4894d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
4895d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
4896d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
4897d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
4898d2a7ac5dSMat Martineau 		}
4899d2a7ac5dSMat Martineau 
4900d2a7ac5dSMat Martineau 		break;
4901d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4902d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4903d2a7ac5dSMat Martineau 		break;
4904d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4905d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4906d2a7ac5dSMat Martineau 		break;
4907d2a7ac5dSMat Martineau 	}
4908d2a7ac5dSMat Martineau 
4909d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4910d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4911d2a7ac5dSMat Martineau 		kfree_skb(skb);
4912d2a7ac5dSMat Martineau 	}
4913d2a7ac5dSMat Martineau 
4914d2a7ac5dSMat Martineau 	return err;
4915d2a7ac5dSMat Martineau }
4916d2a7ac5dSMat Martineau 
4917d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
4918d2a7ac5dSMat Martineau {
4919d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
4920d2a7ac5dSMat Martineau 	u16 unacked;
4921d2a7ac5dSMat Martineau 
4922d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
4923d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
4924d2a7ac5dSMat Martineau }
4925d2a7ac5dSMat Martineau 
4926cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4927cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
49280a708f8fSGustavo F. Padovan {
4929d2a7ac5dSMat Martineau 	int err = 0;
4930d2a7ac5dSMat Martineau 
4931d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
4932d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
4933d2a7ac5dSMat Martineau 
4934d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
4935d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
4936d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
4937d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
4938d2a7ac5dSMat Martineau 			break;
4939d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
4940d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
4941d2a7ac5dSMat Martineau 						       event);
4942d2a7ac5dSMat Martineau 			break;
4943d2a7ac5dSMat Martineau 		default:
4944d2a7ac5dSMat Martineau 			/* shut it down */
4945d2a7ac5dSMat Martineau 			break;
4946d2a7ac5dSMat Martineau 		}
4947d2a7ac5dSMat Martineau 	} else {
4948d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
4949d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
4950d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
4951d2a7ac5dSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4952d2a7ac5dSMat Martineau 	}
4953d2a7ac5dSMat Martineau 
4954d2a7ac5dSMat Martineau 	return err;
4955cec8ab6eSMat Martineau }
4956cec8ab6eSMat Martineau 
4957cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
4958cec8ab6eSMat Martineau 			   struct sk_buff *skb)
4959cec8ab6eSMat Martineau {
49604b51dae9SMat Martineau 	int err = 0;
49614b51dae9SMat Martineau 
49624b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
49634b51dae9SMat Martineau 	       chan->rx_state);
49644b51dae9SMat Martineau 
49654b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
49664b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
49674b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
49684b51dae9SMat Martineau 
49694b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
49704b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
49714b51dae9SMat Martineau 
49724b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
49734b51dae9SMat Martineau 
49744b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
49754b51dae9SMat Martineau 	} else {
49764b51dae9SMat Martineau 		if (chan->sdu) {
49774b51dae9SMat Martineau 			kfree_skb(chan->sdu);
49784b51dae9SMat Martineau 			chan->sdu = NULL;
49794b51dae9SMat Martineau 		}
49804b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
49814b51dae9SMat Martineau 		chan->sdu_len = 0;
49824b51dae9SMat Martineau 
49834b51dae9SMat Martineau 		if (skb) {
49844b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
49854b51dae9SMat Martineau 			kfree_skb(skb);
49864b51dae9SMat Martineau 		}
49874b51dae9SMat Martineau 	}
49884b51dae9SMat Martineau 
49894b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
49904b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
49914b51dae9SMat Martineau 
49924b51dae9SMat Martineau 	return err;
4993cec8ab6eSMat Martineau }
4994cec8ab6eSMat Martineau 
4995cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
4996cec8ab6eSMat Martineau {
4997cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
4998cec8ab6eSMat Martineau 	u16 len;
4999cec8ab6eSMat Martineau 	u8 event;
50000a708f8fSGustavo F. Padovan 
5001b76bbd66SMat Martineau 	__unpack_control(chan, skb);
5002b76bbd66SMat Martineau 
50030a708f8fSGustavo F. Padovan 	len = skb->len;
50040a708f8fSGustavo F. Padovan 
50050a708f8fSGustavo F. Padovan 	/*
50060a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
50070a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
5008cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
50090a708f8fSGustavo F. Padovan 	 */
501047d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
50110a708f8fSGustavo F. Padovan 		goto drop;
50120a708f8fSGustavo F. Padovan 
5013cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
501403a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
50150a708f8fSGustavo F. Padovan 
501647d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
501703a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
50180a708f8fSGustavo F. Padovan 
501947d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
50208c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
50210a708f8fSGustavo F. Padovan 		goto drop;
50220a708f8fSGustavo F. Padovan 	}
50230a708f8fSGustavo F. Padovan 
5024cec8ab6eSMat Martineau 	if (!control->sframe) {
5025cec8ab6eSMat Martineau 		int err;
50260a708f8fSGustavo F. Padovan 
5027cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
5028cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
5029cec8ab6eSMat Martineau 		       control->txseq);
5030836be934SAndrei Emeltchenko 
5031cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
5032cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
5033cec8ab6eSMat Martineau 		 */
5034cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
50350a708f8fSGustavo F. Padovan 			goto drop;
50360a708f8fSGustavo F. Padovan 
5037cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
5038cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
5039cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
50400a708f8fSGustavo F. Padovan 		} else {
5041cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
5042cec8ab6eSMat Martineau 		}
5043cec8ab6eSMat Martineau 
5044cec8ab6eSMat Martineau 		if (err)
5045cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
5046cec8ab6eSMat Martineau 					       ECONNRESET);
5047cec8ab6eSMat Martineau 	} else {
5048cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
5049cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5050cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5051cec8ab6eSMat Martineau 		};
5052cec8ab6eSMat Martineau 
5053cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
5054cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
5055cec8ab6eSMat Martineau 			goto drop;
5056cec8ab6eSMat Martineau 
5057cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5058cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
5059cec8ab6eSMat Martineau 		       control->super);
5060cec8ab6eSMat Martineau 
50610a708f8fSGustavo F. Padovan 		if (len != 0) {
50620a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
50638c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
50640a708f8fSGustavo F. Padovan 			goto drop;
50650a708f8fSGustavo F. Padovan 		}
50660a708f8fSGustavo F. Padovan 
5067cec8ab6eSMat Martineau 		/* Validate F and P bits */
5068cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
5069cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5070cec8ab6eSMat Martineau 			goto drop;
5071cec8ab6eSMat Martineau 
5072cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
5073cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
5074cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
50750a708f8fSGustavo F. Padovan 	}
50760a708f8fSGustavo F. Padovan 
50770a708f8fSGustavo F. Padovan 	return 0;
50780a708f8fSGustavo F. Padovan 
50790a708f8fSGustavo F. Padovan drop:
50800a708f8fSGustavo F. Padovan 	kfree_skb(skb);
50810a708f8fSGustavo F. Padovan 	return 0;
50820a708f8fSGustavo F. Padovan }
50830a708f8fSGustavo F. Padovan 
50840a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
50850a708f8fSGustavo F. Padovan {
508648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
50870a708f8fSGustavo F. Padovan 
5088baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
508948454079SGustavo F. Padovan 	if (!chan) {
50900a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
50916be36555SAndrei Emeltchenko 		/* Drop packet and return */
50923379013bSDan Carpenter 		kfree_skb(skb);
50936be36555SAndrei Emeltchenko 		return 0;
50940a708f8fSGustavo F. Padovan 	}
50950a708f8fSGustavo F. Padovan 
509649208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
50970a708f8fSGustavo F. Padovan 
509889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
50990a708f8fSGustavo F. Padovan 		goto drop;
51000a708f8fSGustavo F. Padovan 
51010c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
51020a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
51030a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
51040a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
51050a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
51060a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
51070a708f8fSGustavo F. Padovan 
51080c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
51090a708f8fSGustavo F. Padovan 			goto drop;
51100a708f8fSGustavo F. Padovan 
511123070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
51120a708f8fSGustavo F. Padovan 			goto done;
51130a708f8fSGustavo F. Padovan 		break;
51140a708f8fSGustavo F. Padovan 
51150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
51160a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
5117cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
51180a708f8fSGustavo F. Padovan 		goto done;
51190a708f8fSGustavo F. Padovan 
51200a708f8fSGustavo F. Padovan 	default:
51210c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
51220a708f8fSGustavo F. Padovan 		break;
51230a708f8fSGustavo F. Padovan 	}
51240a708f8fSGustavo F. Padovan 
51250a708f8fSGustavo F. Padovan drop:
51260a708f8fSGustavo F. Padovan 	kfree_skb(skb);
51270a708f8fSGustavo F. Padovan 
51280a708f8fSGustavo F. Padovan done:
51296be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
51300a708f8fSGustavo F. Padovan 
51310a708f8fSGustavo F. Padovan 	return 0;
51320a708f8fSGustavo F. Padovan }
51330a708f8fSGustavo F. Padovan 
51340a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
51350a708f8fSGustavo F. Padovan {
513623691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
51370a708f8fSGustavo F. Padovan 
5138c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
513923691d75SGustavo F. Padovan 	if (!chan)
51400a708f8fSGustavo F. Padovan 		goto drop;
51410a708f8fSGustavo F. Padovan 
51425b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
51430a708f8fSGustavo F. Padovan 
514489bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
51450a708f8fSGustavo F. Padovan 		goto drop;
51460a708f8fSGustavo F. Padovan 
5147e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
51480a708f8fSGustavo F. Padovan 		goto drop;
51490a708f8fSGustavo F. Padovan 
515023070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
51515b4cedaaSAndrei Emeltchenko 		return 0;
51520a708f8fSGustavo F. Padovan 
51530a708f8fSGustavo F. Padovan drop:
51540a708f8fSGustavo F. Padovan 	kfree_skb(skb);
51550a708f8fSGustavo F. Padovan 
51560a708f8fSGustavo F. Padovan 	return 0;
51570a708f8fSGustavo F. Padovan }
51580a708f8fSGustavo F. Padovan 
5159d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5160d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
51619f69bda6SGustavo F. Padovan {
516223691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
51639f69bda6SGustavo F. Padovan 
5164c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
516523691d75SGustavo F. Padovan 	if (!chan)
51669f69bda6SGustavo F. Padovan 		goto drop;
51679f69bda6SGustavo F. Padovan 
51685b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
51699f69bda6SGustavo F. Padovan 
517089bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
51719f69bda6SGustavo F. Padovan 		goto drop;
51729f69bda6SGustavo F. Padovan 
5173e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
51749f69bda6SGustavo F. Padovan 		goto drop;
51759f69bda6SGustavo F. Padovan 
517623070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
51775b4cedaaSAndrei Emeltchenko 		return 0;
51789f69bda6SGustavo F. Padovan 
51799f69bda6SGustavo F. Padovan drop:
51809f69bda6SGustavo F. Padovan 	kfree_skb(skb);
51819f69bda6SGustavo F. Padovan 
51829f69bda6SGustavo F. Padovan 	return 0;
51839f69bda6SGustavo F. Padovan }
51849f69bda6SGustavo F. Padovan 
51850a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
51860a708f8fSGustavo F. Padovan {
51870a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
51880a708f8fSGustavo F. Padovan 	u16 cid, len;
51890a708f8fSGustavo F. Padovan 	__le16 psm;
51900a708f8fSGustavo F. Padovan 
51910a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
51920a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
51930a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
51940a708f8fSGustavo F. Padovan 
51950a708f8fSGustavo F. Padovan 	if (len != skb->len) {
51960a708f8fSGustavo F. Padovan 		kfree_skb(skb);
51970a708f8fSGustavo F. Padovan 		return;
51980a708f8fSGustavo F. Padovan 	}
51990a708f8fSGustavo F. Padovan 
52000a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
52010a708f8fSGustavo F. Padovan 
52020a708f8fSGustavo F. Padovan 	switch (cid) {
52033300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
52040a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
52050a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
52060a708f8fSGustavo F. Padovan 		break;
52070a708f8fSGustavo F. Padovan 
52080a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
5209097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
52100a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
52110a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
52120a708f8fSGustavo F. Padovan 		break;
52130a708f8fSGustavo F. Padovan 
52149f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
52159f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
52169f69bda6SGustavo F. Padovan 		break;
52179f69bda6SGustavo F. Padovan 
5218b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
5219b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
5220b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
5221b501d6a1SAnderson Briglia 		break;
5222b501d6a1SAnderson Briglia 
52230a708f8fSGustavo F. Padovan 	default:
52240a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
52250a708f8fSGustavo F. Padovan 		break;
52260a708f8fSGustavo F. Padovan 	}
52270a708f8fSGustavo F. Padovan }
52280a708f8fSGustavo F. Padovan 
52290a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
52300a708f8fSGustavo F. Padovan 
5231686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
52320a708f8fSGustavo F. Padovan {
52330a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
523423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
52350a708f8fSGustavo F. Padovan 
52360a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
52370a708f8fSGustavo F. Padovan 
52380a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
523923691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
524023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
524123691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
52424343478fSGustavo F. Padovan 
524389bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
52440a708f8fSGustavo F. Padovan 			continue;
52450a708f8fSGustavo F. Padovan 
52460a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
52470a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
524843bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
52490a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
52500a708f8fSGustavo F. Padovan 			exact++;
52510a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
52520a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
525343bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
52540a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
52550a708f8fSGustavo F. Padovan 		}
52560a708f8fSGustavo F. Padovan 	}
525723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
52580a708f8fSGustavo F. Padovan 
52590a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
52600a708f8fSGustavo F. Padovan }
52610a708f8fSGustavo F. Padovan 
5262686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
52630a708f8fSGustavo F. Padovan {
52640a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
52650a708f8fSGustavo F. Padovan 
52660a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
52670a708f8fSGustavo F. Padovan 
52680a708f8fSGustavo F. Padovan 	if (!status) {
52690a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
52700a708f8fSGustavo F. Padovan 		if (conn)
52710a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
52720a708f8fSGustavo F. Padovan 	} else
5273e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
52740a708f8fSGustavo F. Padovan 
52750a708f8fSGustavo F. Padovan 	return 0;
52760a708f8fSGustavo F. Padovan }
52770a708f8fSGustavo F. Padovan 
5278686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
52790a708f8fSGustavo F. Padovan {
52800a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
52810a708f8fSGustavo F. Padovan 
52820a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
52830a708f8fSGustavo F. Padovan 
5284686ebf28SUlisses Furquim 	if (!conn)
52859f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
52860a708f8fSGustavo F. Padovan 	return conn->disc_reason;
52870a708f8fSGustavo F. Padovan }
52880a708f8fSGustavo F. Padovan 
5289686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
52900a708f8fSGustavo F. Padovan {
52910a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
52920a708f8fSGustavo F. Padovan 
5293e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
52940a708f8fSGustavo F. Padovan 	return 0;
52950a708f8fSGustavo F. Padovan }
52960a708f8fSGustavo F. Padovan 
52974343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
52980a708f8fSGustavo F. Padovan {
5299715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
53000a708f8fSGustavo F. Padovan 		return;
53010a708f8fSGustavo F. Padovan 
53020a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
53034343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
5304ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
53054343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
53060f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
53070a708f8fSGustavo F. Padovan 	} else {
53084343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
5309c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
53100a708f8fSGustavo F. Padovan 	}
53110a708f8fSGustavo F. Padovan }
53120a708f8fSGustavo F. Padovan 
5313686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
53140a708f8fSGustavo F. Padovan {
53150a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
531648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
53170a708f8fSGustavo F. Padovan 
53180a708f8fSGustavo F. Padovan 	if (!conn)
53190a708f8fSGustavo F. Padovan 		return 0;
53200a708f8fSGustavo F. Padovan 
53210a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
53220a708f8fSGustavo F. Padovan 
5323160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
532435d4adccSHemant Gupta 		if (!status && encrypt)
5325160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
532617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
5327160dc6acSVinicius Costa Gomes 	}
5328160dc6acSVinicius Costa Gomes 
53293df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
53300a708f8fSGustavo F. Padovan 
53313df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
53326be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
53330a708f8fSGustavo F. Padovan 
5334f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
5335f1cb9af5SVinicius Costa Gomes 
5336f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
5337f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
5338f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
5339cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
5340f1cb9af5SVinicius Costa Gomes 			}
5341f1cb9af5SVinicius Costa Gomes 
53426be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
5343f1cb9af5SVinicius Costa Gomes 			continue;
5344f1cb9af5SVinicius Costa Gomes 		}
5345f1cb9af5SVinicius Costa Gomes 
5346c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
53476be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
53480a708f8fSGustavo F. Padovan 			continue;
53490a708f8fSGustavo F. Padovan 		}
53500a708f8fSGustavo F. Padovan 
535189bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
535289bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
5353a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
5354a7d7723aSGustavo Padovan 
5355c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
5356a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
5357a7d7723aSGustavo Padovan 
53584343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
53596be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
53600a708f8fSGustavo F. Padovan 			continue;
53610a708f8fSGustavo F. Padovan 		}
53620a708f8fSGustavo F. Padovan 
536389bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
53640a708f8fSGustavo F. Padovan 			if (!status) {
53659b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
53660a708f8fSGustavo F. Padovan 			} else {
5367ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
53680a708f8fSGustavo F. Padovan 			}
536989bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
53706be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
53710a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5372df3c3931SJohan Hedberg 			__u16 res, stat;
53730a708f8fSGustavo F. Padovan 
53746be36555SAndrei Emeltchenko 			lock_sock(sk);
53756be36555SAndrei Emeltchenko 
53760a708f8fSGustavo F. Padovan 			if (!status) {
5377c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
5378c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
5379df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
5380df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
5381df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
538205e9a2f6SIlia Kolomisnky 					if (parent)
5383df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
5384df3c3931SJohan Hedberg 				} else {
53850e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
5386df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
5387df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
5388df3c3931SJohan Hedberg 				}
53890a708f8fSGustavo F. Padovan 			} else {
53900e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
5391ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
5392df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
5393df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
53940a708f8fSGustavo F. Padovan 			}
53950a708f8fSGustavo F. Padovan 
53966be36555SAndrei Emeltchenko 			release_sock(sk);
53976be36555SAndrei Emeltchenko 
5398fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5399fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5400df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
5401df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
5402fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5403fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
54040a708f8fSGustavo F. Padovan 		}
54050a708f8fSGustavo F. Padovan 
54066be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
54070a708f8fSGustavo F. Padovan 	}
54080a708f8fSGustavo F. Padovan 
54093df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
54100a708f8fSGustavo F. Padovan 
54110a708f8fSGustavo F. Padovan 	return 0;
54120a708f8fSGustavo F. Padovan }
54130a708f8fSGustavo F. Padovan 
5414686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
54150a708f8fSGustavo F. Padovan {
54160a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
54170a708f8fSGustavo F. Padovan 
54180a708f8fSGustavo F. Padovan 	if (!conn)
54190a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
54200a708f8fSGustavo F. Padovan 
54210a708f8fSGustavo F. Padovan 	if (!conn)
54220a708f8fSGustavo F. Padovan 		goto drop;
54230a708f8fSGustavo F. Padovan 
54240a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
54250a708f8fSGustavo F. Padovan 
54260a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
54270a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
54280a708f8fSGustavo F. Padovan 		int len;
54290a708f8fSGustavo F. Padovan 
54300a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
54310a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
54320a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
54330a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
54340a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
54350a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
54360a708f8fSGustavo F. Padovan 		}
54370a708f8fSGustavo F. Padovan 
54380a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
54390a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
54400a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
54410a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
54420a708f8fSGustavo F. Padovan 			goto drop;
54430a708f8fSGustavo F. Padovan 		}
54440a708f8fSGustavo F. Padovan 
54450a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
54460a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
54470a708f8fSGustavo F. Padovan 
54480a708f8fSGustavo F. Padovan 		if (len == skb->len) {
54490a708f8fSGustavo F. Padovan 			/* Complete frame received */
54500a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
54510a708f8fSGustavo F. Padovan 			return 0;
54520a708f8fSGustavo F. Padovan 		}
54530a708f8fSGustavo F. Padovan 
54540a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
54550a708f8fSGustavo F. Padovan 
54560a708f8fSGustavo F. Padovan 		if (skb->len > len) {
54570a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
54580a708f8fSGustavo F. Padovan 				skb->len, len);
54590a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
54600a708f8fSGustavo F. Padovan 			goto drop;
54610a708f8fSGustavo F. Padovan 		}
54620a708f8fSGustavo F. Padovan 
54630a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
54640a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
54650a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
54660a708f8fSGustavo F. Padovan 			goto drop;
54670a708f8fSGustavo F. Padovan 
54680a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
54690a708f8fSGustavo F. Padovan 								skb->len);
54700a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
54710a708f8fSGustavo F. Padovan 	} else {
54720a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
54730a708f8fSGustavo F. Padovan 
54740a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
54750a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
54760a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
54770a708f8fSGustavo F. Padovan 			goto drop;
54780a708f8fSGustavo F. Padovan 		}
54790a708f8fSGustavo F. Padovan 
54800a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
54810a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
54820a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
54830a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
54840a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
54850a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
54860a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
54870a708f8fSGustavo F. Padovan 			goto drop;
54880a708f8fSGustavo F. Padovan 		}
54890a708f8fSGustavo F. Padovan 
54900a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
54910a708f8fSGustavo F. Padovan 								skb->len);
54920a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
54930a708f8fSGustavo F. Padovan 
54940a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
54950a708f8fSGustavo F. Padovan 			/* Complete frame received */
54960a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
54970a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
54980a708f8fSGustavo F. Padovan 		}
54990a708f8fSGustavo F. Padovan 	}
55000a708f8fSGustavo F. Padovan 
55010a708f8fSGustavo F. Padovan drop:
55020a708f8fSGustavo F. Padovan 	kfree_skb(skb);
55030a708f8fSGustavo F. Padovan 	return 0;
55040a708f8fSGustavo F. Padovan }
55050a708f8fSGustavo F. Padovan 
55060a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
55070a708f8fSGustavo F. Padovan {
550823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
55090a708f8fSGustavo F. Padovan 
5510333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
55110a708f8fSGustavo F. Padovan 
551223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
551323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
55140a708f8fSGustavo F. Padovan 
5515903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
55160a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
55170a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
551889bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
551923691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
552023691d75SGustavo F. Padovan 					c->sec_level, c->mode);
55210a708f8fSGustavo F. Padovan 	}
55220a708f8fSGustavo F. Padovan 
5523333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
55240a708f8fSGustavo F. Padovan 
55250a708f8fSGustavo F. Padovan 	return 0;
55260a708f8fSGustavo F. Padovan }
55270a708f8fSGustavo F. Padovan 
55280a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
55290a708f8fSGustavo F. Padovan {
55300a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
55310a708f8fSGustavo F. Padovan }
55320a708f8fSGustavo F. Padovan 
55330a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
55340a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
55350a708f8fSGustavo F. Padovan 	.read		= seq_read,
55360a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
55370a708f8fSGustavo F. Padovan 	.release	= single_release,
55380a708f8fSGustavo F. Padovan };
55390a708f8fSGustavo F. Padovan 
55400a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
55410a708f8fSGustavo F. Padovan 
554264274518SGustavo F. Padovan int __init l2cap_init(void)
55430a708f8fSGustavo F. Padovan {
55440a708f8fSGustavo F. Padovan 	int err;
55450a708f8fSGustavo F. Padovan 
5546bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
55470a708f8fSGustavo F. Padovan 	if (err < 0)
55480a708f8fSGustavo F. Padovan 		return err;
55490a708f8fSGustavo F. Padovan 
55500a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
55510a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
55520a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
55530a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
55540a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
55550a708f8fSGustavo F. Padovan 	}
55560a708f8fSGustavo F. Padovan 
55570a708f8fSGustavo F. Padovan 	return 0;
55580a708f8fSGustavo F. Padovan }
55590a708f8fSGustavo F. Padovan 
556064274518SGustavo F. Padovan void l2cap_exit(void)
55610a708f8fSGustavo F. Padovan {
55620a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5563bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
55640a708f8fSGustavo F. Padovan }
55650a708f8fSGustavo F. Padovan 
55660a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
55670a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5568