xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision c9e3d5e0)
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 
923*c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
9240a708f8fSGustavo F. Padovan {
925*c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
9260a708f8fSGustavo F. Padovan 
927*c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
928*c9e3d5e0SMat Martineau 
929*c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
930*c9e3d5e0SMat Martineau 	control.sframe = 1;
931*c9e3d5e0SMat Martineau 	control.poll = poll;
932*c9e3d5e0SMat Martineau 
933*c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
934*c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
935*c9e3d5e0SMat Martineau 	else
936*c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
937*c9e3d5e0SMat Martineau 
938*c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
939*c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
9400a708f8fSGustavo F. Padovan }
9410a708f8fSGustavo F. Padovan 
942b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9430a708f8fSGustavo F. Padovan {
944c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9450a708f8fSGustavo F. Padovan }
9460a708f8fSGustavo F. Padovan 
9479b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9489b27f350SAndrei Emeltchenko {
9499b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9509b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9519b27f350SAndrei Emeltchenko 
9529b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9539b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9549b27f350SAndrei Emeltchenko 
9559b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9569b27f350SAndrei Emeltchenko 
9579b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9589b27f350SAndrei Emeltchenko 
9599b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9609b27f350SAndrei Emeltchenko }
9619b27f350SAndrei Emeltchenko 
9629f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9639f0caeb1SVinicius Costa Gomes {
9649f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9659f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9669f0caeb1SVinicius Costa Gomes 
9679f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9689f0caeb1SVinicius Costa Gomes 
9699f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9709f0caeb1SVinicius Costa Gomes 
9719f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9729f0caeb1SVinicius Costa Gomes 
9732827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9749f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9759f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9769f0caeb1SVinicius Costa Gomes 
9779f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9789f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9799f0caeb1SVinicius Costa Gomes 
9809f0caeb1SVinicius Costa Gomes 	if (parent)
9819f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9829f0caeb1SVinicius Costa Gomes 
9839f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9849f0caeb1SVinicius Costa Gomes }
9859f0caeb1SVinicius Costa Gomes 
986fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9870a708f8fSGustavo F. Padovan {
9888c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9890a708f8fSGustavo F. Padovan 
9909f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9919f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9929f0caeb1SVinicius Costa Gomes 		return;
9939f0caeb1SVinicius Costa Gomes 	}
9949f0caeb1SVinicius Costa Gomes 
9950a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9960a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9970a708f8fSGustavo F. Padovan 			return;
9980a708f8fSGustavo F. Padovan 
999d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
10009b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
10019b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10020a708f8fSGustavo F. Padovan 	} else {
10030a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
10040a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
10050a708f8fSGustavo F. Padovan 
10060a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
10070a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
10080a708f8fSGustavo F. Padovan 
1009ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
10100a708f8fSGustavo F. Padovan 
10110a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
10120a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
10130a708f8fSGustavo F. Padovan 	}
10140a708f8fSGustavo F. Padovan }
10150a708f8fSGustavo F. Padovan 
10160a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
10170a708f8fSGustavo F. Padovan {
10180a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
10190a708f8fSGustavo F. Padovan 	if (!disable_ertm)
10200a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
10210a708f8fSGustavo F. Padovan 
10220a708f8fSGustavo F. Padovan 	switch (mode) {
10230a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
10240a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
10250a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
10260a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
10270a708f8fSGustavo F. Padovan 	default:
10280a708f8fSGustavo F. Padovan 		return 0x00;
10290a708f8fSGustavo F. Padovan 	}
10300a708f8fSGustavo F. Padovan }
10310a708f8fSGustavo F. Padovan 
10324519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
10330a708f8fSGustavo F. Padovan {
10346be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
10350a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
10360a708f8fSGustavo F. Padovan 
10370a708f8fSGustavo F. Padovan 	if (!conn)
10380a708f8fSGustavo F. Padovan 		return;
10390a708f8fSGustavo F. Padovan 
10400c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
10411a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
10421a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
10431a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
10440a708f8fSGustavo F. Padovan 	}
10450a708f8fSGustavo F. Padovan 
1046fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1047fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10480a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10490a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10500a708f8fSGustavo F. Padovan 
10516be36555SAndrei Emeltchenko 	lock_sock(sk);
10520e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10532e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10546be36555SAndrei Emeltchenko 	release_sock(sk);
10550a708f8fSGustavo F. Padovan }
10560a708f8fSGustavo F. Padovan 
10570a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10580a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10590a708f8fSGustavo F. Padovan {
10603df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10610a708f8fSGustavo F. Padovan 
10620a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10630a708f8fSGustavo F. Padovan 
10643df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10650a708f8fSGustavo F. Padovan 
10663df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
106748454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1068baa7e1faSGustavo F. Padovan 
10696be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10700a708f8fSGustavo F. Padovan 
1071715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10726be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10730a708f8fSGustavo F. Padovan 			continue;
10740a708f8fSGustavo F. Padovan 		}
10750a708f8fSGustavo F. Padovan 
107689bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1077d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1078b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10796be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10800a708f8fSGustavo F. Padovan 				continue;
10810a708f8fSGustavo F. Padovan 			}
10820a708f8fSGustavo F. Padovan 
1083c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1084c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1085c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10860f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10876be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10880a708f8fSGustavo F. Padovan 				continue;
10890a708f8fSGustavo F. Padovan 			}
10900a708f8fSGustavo F. Padovan 
10919b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10920a708f8fSGustavo F. Padovan 
109389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10940a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10950a708f8fSGustavo F. Padovan 			char buf[128];
1096fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1097fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10980a708f8fSGustavo F. Padovan 
1099d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
11006be36555SAndrei Emeltchenko 				lock_sock(sk);
1101c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1102c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
11030a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
11040a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11050a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
110605e9a2f6SIlia Kolomisnky 					if (parent)
11070a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
11080a708f8fSGustavo F. Padovan 
11090a708f8fSGustavo F. Padovan 				} else {
11100e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
11110a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
11120a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
11130a708f8fSGustavo F. Padovan 				}
11146be36555SAndrei Emeltchenko 				release_sock(sk);
11150a708f8fSGustavo F. Padovan 			} else {
11160a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11170a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
11180a708f8fSGustavo F. Padovan 			}
11190a708f8fSGustavo F. Padovan 
1120fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1121fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
11220a708f8fSGustavo F. Padovan 
1123c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
11240a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
11256be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
11260a708f8fSGustavo F. Padovan 				continue;
11270a708f8fSGustavo F. Padovan 			}
11280a708f8fSGustavo F. Padovan 
1129c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
11300a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
113173ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
113273ffa904SGustavo F. Padovan 			chan->num_conf_req++;
11330a708f8fSGustavo F. Padovan 		}
11340a708f8fSGustavo F. Padovan 
11356be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
11360a708f8fSGustavo F. Padovan 	}
11370a708f8fSGustavo F. Padovan 
11383df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
11390a708f8fSGustavo F. Padovan }
11400a708f8fSGustavo F. Padovan 
1141c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1142b62f328bSVille Tervo  * Returns closest match, locked.
1143b62f328bSVille Tervo  */
1144d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1145c2287681SIdo Yariv 						    bdaddr_t *src,
1146c2287681SIdo Yariv 						    bdaddr_t *dst)
1147b62f328bSVille Tervo {
114823691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1149b62f328bSVille Tervo 
115023691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1151b62f328bSVille Tervo 
115223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
115323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1154fe4128e0SGustavo F. Padovan 
115589bc500eSGustavo F. Padovan 		if (state && c->state != state)
1156b62f328bSVille Tervo 			continue;
1157b62f328bSVille Tervo 
115823691d75SGustavo F. Padovan 		if (c->scid == cid) {
1159c2287681SIdo Yariv 			int src_match, dst_match;
1160c2287681SIdo Yariv 			int src_any, dst_any;
1161c2287681SIdo Yariv 
1162b62f328bSVille Tervo 			/* Exact match. */
1163c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1164c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1165c2287681SIdo Yariv 			if (src_match && dst_match) {
116623691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
116723691d75SGustavo F. Padovan 				return c;
116823691d75SGustavo F. Padovan 			}
1169b62f328bSVille Tervo 
1170b62f328bSVille Tervo 			/* Closest match */
1171c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1172c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1173c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1174c2287681SIdo Yariv 			    (src_any && dst_any))
117523691d75SGustavo F. Padovan 				c1 = c;
1176b62f328bSVille Tervo 		}
1177b62f328bSVille Tervo 	}
1178280f294fSGustavo F. Padovan 
117923691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1180b62f328bSVille Tervo 
118123691d75SGustavo F. Padovan 	return c1;
1182b62f328bSVille Tervo }
1183b62f328bSVille Tervo 
1184b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1185b62f328bSVille Tervo {
1186c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
118723691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1188b62f328bSVille Tervo 
1189b62f328bSVille Tervo 	BT_DBG("");
1190b62f328bSVille Tervo 
1191b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
119223691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1193c2287681SIdo Yariv 					  conn->src, conn->dst);
119423691d75SGustavo F. Padovan 	if (!pchan)
1195b62f328bSVille Tervo 		return;
1196b62f328bSVille Tervo 
119723691d75SGustavo F. Padovan 	parent = pchan->sk;
119823691d75SGustavo F. Padovan 
1199aa2ac881SGustavo F. Padovan 	lock_sock(parent);
120062f3a2cfSGustavo F. Padovan 
1201b62f328bSVille Tervo 	/* Check for backlog size */
1202b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1203b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1204b62f328bSVille Tervo 		goto clean;
1205b62f328bSVille Tervo 	}
1206b62f328bSVille Tervo 
120780808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
120880808e43SGustavo F. Padovan 	if (!chan)
1209b62f328bSVille Tervo 		goto clean;
1210b62f328bSVille Tervo 
121180808e43SGustavo F. Padovan 	sk = chan->sk;
12125d41ce1dSGustavo F. Padovan 
1213b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1214b62f328bSVille Tervo 
1215b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1216b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1217b62f328bSVille Tervo 
1218d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1219d1010240SGustavo F. Padovan 
12203d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
122148454079SGustavo F. Padovan 
1222c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1223b62f328bSVille Tervo 
12240e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1225b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1226b62f328bSVille Tervo 
1227b62f328bSVille Tervo clean:
1228aa2ac881SGustavo F. Padovan 	release_sock(parent);
1229b62f328bSVille Tervo }
1230b62f328bSVille Tervo 
12310a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
12320a708f8fSGustavo F. Padovan {
123348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12340a708f8fSGustavo F. Padovan 
12350a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12360a708f8fSGustavo F. Padovan 
1237b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1238b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1239b62f328bSVille Tervo 
1240160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1241160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1242160dc6acSVinicius Costa Gomes 
12433df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12440a708f8fSGustavo F. Padovan 
12453df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1246baa7e1faSGustavo F. Padovan 
12476be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12480a708f8fSGustavo F. Padovan 
124963128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1250b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1251cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1252acd7d370SVille Tervo 
125363128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12546be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1255c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12566be36555SAndrei Emeltchenko 			lock_sock(sk);
12570e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12580a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12596be36555SAndrei Emeltchenko 			release_sock(sk);
1260b501d6a1SAnderson Briglia 
126189bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1262fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12630a708f8fSGustavo F. Padovan 
12646be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12650a708f8fSGustavo F. Padovan 	}
12660a708f8fSGustavo F. Padovan 
12673df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12680a708f8fSGustavo F. Padovan }
12690a708f8fSGustavo F. Padovan 
12700a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12710a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12720a708f8fSGustavo F. Padovan {
127348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12740a708f8fSGustavo F. Padovan 
12750a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12760a708f8fSGustavo F. Padovan 
12773df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12780a708f8fSGustavo F. Padovan 
12793df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1280ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12812e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12820a708f8fSGustavo F. Padovan 	}
12830a708f8fSGustavo F. Padovan 
12843df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12850a708f8fSGustavo F. Padovan }
12860a708f8fSGustavo F. Padovan 
1287f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12880a708f8fSGustavo F. Padovan {
1289f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1290030013d8SGustavo F. Padovan 							info_timer.work);
12910a708f8fSGustavo F. Padovan 
12920a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12930a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12940a708f8fSGustavo F. Padovan 
12950a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12960a708f8fSGustavo F. Padovan }
12970a708f8fSGustavo F. Padovan 
12985d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12995d3de7dfSVinicius Costa Gomes {
13005d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
13015d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
13025d3de7dfSVinicius Costa Gomes 
13035d3de7dfSVinicius Costa Gomes 	if (!conn)
13045d3de7dfSVinicius Costa Gomes 		return;
13055d3de7dfSVinicius Costa Gomes 
13065d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
13075d3de7dfSVinicius Costa Gomes 
13085d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
13095d3de7dfSVinicius Costa Gomes 
13103df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13113df91ea2SAndrei Emeltchenko 
13125d3de7dfSVinicius Costa Gomes 	/* Kill channels */
13135d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
131461d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
13156be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13166be36555SAndrei Emeltchenko 
13175d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
13186be36555SAndrei Emeltchenko 
13196be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13206be36555SAndrei Emeltchenko 
13215d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
132261d6ef3eSMat Martineau 		l2cap_chan_put(chan);
13235d3de7dfSVinicius Costa Gomes 	}
13245d3de7dfSVinicius Costa Gomes 
13253df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
13263df91ea2SAndrei Emeltchenko 
132773d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
132873d80debSLuiz Augusto von Dentz 
13295d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1330127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
13315d3de7dfSVinicius Costa Gomes 
133251a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1333127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
13348aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1335d26a2345SVinicius Costa Gomes 	}
13365d3de7dfSVinicius Costa Gomes 
13375d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
13385d3de7dfSVinicius Costa Gomes 	kfree(conn);
13395d3de7dfSVinicius Costa Gomes }
13405d3de7dfSVinicius Costa Gomes 
13416c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
13425d3de7dfSVinicius Costa Gomes {
13436c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
13446c9d42a1SGustavo F. Padovan 						security_timer.work);
13455d3de7dfSVinicius Costa Gomes 
13465d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
13475d3de7dfSVinicius Costa Gomes }
13485d3de7dfSVinicius Costa Gomes 
13490a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13500a708f8fSGustavo F. Padovan {
13510a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
135273d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13530a708f8fSGustavo F. Padovan 
13540a708f8fSGustavo F. Padovan 	if (conn || status)
13550a708f8fSGustavo F. Padovan 		return conn;
13560a708f8fSGustavo F. Padovan 
135773d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
135873d80debSLuiz Augusto von Dentz 	if (!hchan)
13590a708f8fSGustavo F. Padovan 		return NULL;
13600a708f8fSGustavo F. Padovan 
136173d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
136273d80debSLuiz Augusto von Dentz 	if (!conn) {
136373d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
136473d80debSLuiz Augusto von Dentz 		return NULL;
136573d80debSLuiz Augusto von Dentz 	}
136673d80debSLuiz Augusto von Dentz 
13670a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13680a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
136973d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13700a708f8fSGustavo F. Padovan 
137173d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13720a708f8fSGustavo F. Padovan 
1373acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1374acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1375acd7d370SVille Tervo 	else
13760a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1377acd7d370SVille Tervo 
13780a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13790a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13800a708f8fSGustavo F. Padovan 
13810a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13820a708f8fSGustavo F. Padovan 
13830a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13843df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1385baa7e1faSGustavo F. Padovan 
1386baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13870a708f8fSGustavo F. Padovan 
13885d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13896c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13905d3de7dfSVinicius Costa Gomes 	else
1391030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13920a708f8fSGustavo F. Padovan 
13939f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13940a708f8fSGustavo F. Padovan 
13950a708f8fSGustavo F. Padovan 	return conn;
13960a708f8fSGustavo F. Padovan }
13970a708f8fSGustavo F. Padovan 
13980a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13990a708f8fSGustavo F. Padovan 
1400c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
14010a708f8fSGustavo F. Padovan  * Returns closest match.
14020a708f8fSGustavo F. Padovan  */
1403c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1404c2287681SIdo Yariv 						   bdaddr_t *src,
1405c2287681SIdo Yariv 						   bdaddr_t *dst)
14060a708f8fSGustavo F. Padovan {
140723691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
14080a708f8fSGustavo F. Padovan 
140923691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
14100a708f8fSGustavo F. Padovan 
141123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
141223691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1413fe4128e0SGustavo F. Padovan 
141489bc500eSGustavo F. Padovan 		if (state && c->state != state)
14150a708f8fSGustavo F. Padovan 			continue;
14160a708f8fSGustavo F. Padovan 
141723691d75SGustavo F. Padovan 		if (c->psm == psm) {
1418c2287681SIdo Yariv 			int src_match, dst_match;
1419c2287681SIdo Yariv 			int src_any, dst_any;
1420c2287681SIdo Yariv 
14210a708f8fSGustavo F. Padovan 			/* Exact match. */
1422c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1423c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1424c2287681SIdo Yariv 			if (src_match && dst_match) {
1425a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
142623691d75SGustavo F. Padovan 				return c;
142723691d75SGustavo F. Padovan 			}
14280a708f8fSGustavo F. Padovan 
14290a708f8fSGustavo F. Padovan 			/* Closest match */
1430c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1431c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1432c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1433c2287681SIdo Yariv 			    (src_any && dst_any))
143423691d75SGustavo F. Padovan 				c1 = c;
14350a708f8fSGustavo F. Padovan 		}
14360a708f8fSGustavo F. Padovan 	}
14370a708f8fSGustavo F. Padovan 
143823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
14390a708f8fSGustavo F. Padovan 
144023691d75SGustavo F. Padovan 	return c1;
14410a708f8fSGustavo F. Padovan }
14420a708f8fSGustavo F. Padovan 
14438e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
14448e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14450a708f8fSGustavo F. Padovan {
14465d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14470a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14480a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14490a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14500a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14510a708f8fSGustavo F. Padovan 	__u8 auth_type;
14520a708f8fSGustavo F. Padovan 	int err;
14530a708f8fSGustavo F. Padovan 
14548e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14558e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14560a708f8fSGustavo F. Padovan 
14570a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14580a708f8fSGustavo F. Padovan 	if (!hdev)
14590a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14600a708f8fSGustavo F. Padovan 
146109fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14620a708f8fSGustavo F. Padovan 
14636be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
146403a00194SGustavo F. Padovan 
146503a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
146603a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
146703a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
146803a00194SGustavo F. Padovan 		err = -EINVAL;
146903a00194SGustavo F. Padovan 		goto done;
147003a00194SGustavo F. Padovan 	}
147103a00194SGustavo F. Padovan 
147203a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
147303a00194SGustavo F. Padovan 		err = -EINVAL;
147403a00194SGustavo F. Padovan 		goto done;
147503a00194SGustavo F. Padovan 	}
147603a00194SGustavo F. Padovan 
147703a00194SGustavo F. Padovan 	switch (chan->mode) {
147803a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
147903a00194SGustavo F. Padovan 		break;
148003a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
148103a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
148203a00194SGustavo F. Padovan 		if (!disable_ertm)
148303a00194SGustavo F. Padovan 			break;
148403a00194SGustavo F. Padovan 		/* fall through */
148503a00194SGustavo F. Padovan 	default:
148603a00194SGustavo F. Padovan 		err = -ENOTSUPP;
148703a00194SGustavo F. Padovan 		goto done;
148803a00194SGustavo F. Padovan 	}
148903a00194SGustavo F. Padovan 
14906be36555SAndrei Emeltchenko 	lock_sock(sk);
14916be36555SAndrei Emeltchenko 
149203a00194SGustavo F. Padovan 	switch (sk->sk_state) {
149303a00194SGustavo F. Padovan 	case BT_CONNECT:
149403a00194SGustavo F. Padovan 	case BT_CONNECT2:
149503a00194SGustavo F. Padovan 	case BT_CONFIG:
149603a00194SGustavo F. Padovan 		/* Already connecting */
149703a00194SGustavo F. Padovan 		err = 0;
14986be36555SAndrei Emeltchenko 		release_sock(sk);
149903a00194SGustavo F. Padovan 		goto done;
150003a00194SGustavo F. Padovan 
150103a00194SGustavo F. Padovan 	case BT_CONNECTED:
150203a00194SGustavo F. Padovan 		/* Already connected */
150303a00194SGustavo F. Padovan 		err = -EISCONN;
15046be36555SAndrei Emeltchenko 		release_sock(sk);
150503a00194SGustavo F. Padovan 		goto done;
150603a00194SGustavo F. Padovan 
150703a00194SGustavo F. Padovan 	case BT_OPEN:
150803a00194SGustavo F. Padovan 	case BT_BOUND:
150903a00194SGustavo F. Padovan 		/* Can connect */
151003a00194SGustavo F. Padovan 		break;
151103a00194SGustavo F. Padovan 
151203a00194SGustavo F. Padovan 	default:
151303a00194SGustavo F. Padovan 		err = -EBADFD;
15146be36555SAndrei Emeltchenko 		release_sock(sk);
151503a00194SGustavo F. Padovan 		goto done;
151603a00194SGustavo F. Padovan 	}
151703a00194SGustavo F. Padovan 
151803a00194SGustavo F. Padovan 	/* Set destination address and psm */
15199219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
15206be36555SAndrei Emeltchenko 
15216be36555SAndrei Emeltchenko 	release_sock(sk);
15226be36555SAndrei Emeltchenko 
152303a00194SGustavo F. Padovan 	chan->psm = psm;
152403a00194SGustavo F. Padovan 	chan->dcid = cid;
15250a708f8fSGustavo F. Padovan 
15264343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
15270a708f8fSGustavo F. Padovan 
1528fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
15298e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
15304343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1531acd7d370SVille Tervo 	else
15328e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
15334343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1534acd7d370SVille Tervo 
153530e76272SVille Tervo 	if (IS_ERR(hcon)) {
153630e76272SVille Tervo 		err = PTR_ERR(hcon);
15370a708f8fSGustavo F. Padovan 		goto done;
153830e76272SVille Tervo 	}
15390a708f8fSGustavo F. Padovan 
15400a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
15410a708f8fSGustavo F. Padovan 	if (!conn) {
15420a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
154330e76272SVille Tervo 		err = -ENOMEM;
15440a708f8fSGustavo F. Padovan 		goto done;
15450a708f8fSGustavo F. Padovan 	}
15460a708f8fSGustavo F. Padovan 
15479f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15489f0caeb1SVinicius Costa Gomes 		err = 0;
15499f0caeb1SVinicius Costa Gomes 
15509f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15519f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15529f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15539f0caeb1SVinicius Costa Gomes 		}
15549f0caeb1SVinicius Costa Gomes 
15559f0caeb1SVinicius Costa Gomes 		if (err)
15569f0caeb1SVinicius Costa Gomes 			goto done;
15579f0caeb1SVinicius Costa Gomes 	}
15589f0caeb1SVinicius Costa Gomes 
15590a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15600a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15610a708f8fSGustavo F. Padovan 
15626be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
156348454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15646be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
156548454079SGustavo F. Padovan 
15666be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1567c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15680a708f8fSGustavo F. Padovan 
15690a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1570715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1571c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1572d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15736be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15740a708f8fSGustavo F. Padovan 		} else
1575fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15760a708f8fSGustavo F. Padovan 	}
15770a708f8fSGustavo F. Padovan 
157830e76272SVille Tervo 	err = 0;
157930e76272SVille Tervo 
15800a708f8fSGustavo F. Padovan done:
15816be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
158209fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15830a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15840a708f8fSGustavo F. Padovan 	return err;
15850a708f8fSGustavo F. Padovan }
15860a708f8fSGustavo F. Padovan 
1587dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15880a708f8fSGustavo F. Padovan {
15898c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15900a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15910a708f8fSGustavo F. Padovan 	int err = 0;
15920a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15930a708f8fSGustavo F. Padovan 
15940a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15950a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1596a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15970a708f8fSGustavo F. Padovan 		if (!timeo)
15980a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15990a708f8fSGustavo F. Padovan 
16000a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
16010a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
16020a708f8fSGustavo F. Padovan 			break;
16030a708f8fSGustavo F. Padovan 		}
16040a708f8fSGustavo F. Padovan 
16050a708f8fSGustavo F. Padovan 		release_sock(sk);
16060a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
16070a708f8fSGustavo F. Padovan 		lock_sock(sk);
1608a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
16090a708f8fSGustavo F. Padovan 
16100a708f8fSGustavo F. Padovan 		err = sock_error(sk);
16110a708f8fSGustavo F. Padovan 		if (err)
16120a708f8fSGustavo F. Padovan 			break;
16130a708f8fSGustavo F. Padovan 	}
16140a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
16150a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
16160a708f8fSGustavo F. Padovan 	return err;
16170a708f8fSGustavo F. Padovan }
16180a708f8fSGustavo F. Padovan 
1619721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
16200a708f8fSGustavo F. Padovan {
1621721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1622721c4181SGustavo F. Padovan 							monitor_timer.work);
16230a708f8fSGustavo F. Padovan 
1624525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
16250a708f8fSGustavo F. Padovan 
16266be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16276be36555SAndrei Emeltchenko 
16282c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
16298c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16306be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16318d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
16320a708f8fSGustavo F. Padovan 		return;
16330a708f8fSGustavo F. Padovan 	}
16340a708f8fSGustavo F. Padovan 
16356a026610SGustavo F. Padovan 	chan->retry_count++;
16361a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16370a708f8fSGustavo F. Padovan 
1638525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16396be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16408d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16410a708f8fSGustavo F. Padovan }
16420a708f8fSGustavo F. Padovan 
1643721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
16440a708f8fSGustavo F. Padovan {
1645721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1646721c4181SGustavo F. Padovan 							retrans_timer.work);
16470a708f8fSGustavo F. Padovan 
164849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16490a708f8fSGustavo F. Padovan 
16506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16516be36555SAndrei Emeltchenko 
16526a026610SGustavo F. Padovan 	chan->retry_count = 1;
16531a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16540a708f8fSGustavo F. Padovan 
1655e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16560a708f8fSGustavo F. Padovan 
1657525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16586be36555SAndrei Emeltchenko 
16596be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16608d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16610a708f8fSGustavo F. Padovan }
16620a708f8fSGustavo F. Padovan 
16633733937dSMat Martineau static int l2cap_streaming_send(struct l2cap_chan *chan,
16643733937dSMat Martineau 				struct sk_buff_head *skbs)
16650a708f8fSGustavo F. Padovan {
16660a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16673733937dSMat Martineau 	struct l2cap_ctrl *control;
16680a708f8fSGustavo F. Padovan 
16693733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
16703733937dSMat Martineau 
16713733937dSMat Martineau 	if (chan->state != BT_CONNECTED)
16723733937dSMat Martineau 		return -ENOTCONN;
16733733937dSMat Martineau 
16743733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
16753733937dSMat Martineau 
16763733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
16773733937dSMat Martineau 
16783733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
16793733937dSMat Martineau 
16803733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
16813733937dSMat Martineau 		control = &bt_cb(skb)->control;
16823733937dSMat Martineau 
16833733937dSMat Martineau 		control->reqseq = 0;
16843733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
16853733937dSMat Martineau 
16863733937dSMat Martineau 		__pack_control(chan, control, skb);
16870a708f8fSGustavo F. Padovan 
168847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
16893733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
16903733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
16910a708f8fSGustavo F. Padovan 		}
16920a708f8fSGustavo F. Padovan 
16934343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16940a708f8fSGustavo F. Padovan 
16953733937dSMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
16963733937dSMat Martineau 
1697836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16983733937dSMat Martineau 		chan->frames_sent++;
16990a708f8fSGustavo F. Padovan 	}
17003733937dSMat Martineau 
17013733937dSMat Martineau 	return 0;
17020a708f8fSGustavo F. Padovan }
17030a708f8fSGustavo F. Padovan 
170467c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
17050a708f8fSGustavo F. Padovan {
17060a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
170718a48e76SMat Martineau 	struct l2cap_ctrl *control;
170818a48e76SMat Martineau 	int sent = 0;
170918a48e76SMat Martineau 
171018a48e76SMat Martineau 	BT_DBG("chan %p", chan);
17110a708f8fSGustavo F. Padovan 
171289bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17130a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17140a708f8fSGustavo F. Padovan 
171594122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
171694122bbeSMat Martineau 		return 0;
171794122bbeSMat Martineau 
171818a48e76SMat Martineau 	while (chan->tx_send_head &&
171918a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
172018a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
17210a708f8fSGustavo F. Padovan 
172218a48e76SMat Martineau 		skb = chan->tx_send_head;
17230a708f8fSGustavo F. Padovan 
172418a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
172518a48e76SMat Martineau 		control = &bt_cb(skb)->control;
17260a708f8fSGustavo F. Padovan 
1727e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
172818a48e76SMat Martineau 			control->final = 1;
1729e2ab4353SGustavo F. Padovan 
173018a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
173118a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
173218a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
17330a708f8fSGustavo F. Padovan 
173418a48e76SMat Martineau 		__pack_control(chan, control, skb);
17350a708f8fSGustavo F. Padovan 
173647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
173718a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
173818a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
17390a708f8fSGustavo F. Padovan 		}
17400a708f8fSGustavo F. Padovan 
174118a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
174218a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
174318a48e76SMat Martineau 		 */
174418a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
174518a48e76SMat Martineau 
174618a48e76SMat Martineau 		if (!tx_skb)
174718a48e76SMat Martineau 			break;
17480a708f8fSGustavo F. Padovan 
17491a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17500a708f8fSGustavo F. Padovan 
1751836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17526a026610SGustavo F. Padovan 		chan->unacked_frames++;
17536a026610SGustavo F. Padovan 		chan->frames_sent++;
175418a48e76SMat Martineau 		sent++;
17550a708f8fSGustavo F. Padovan 
175658d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
175758d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17580a708f8fSGustavo F. Padovan 		else
175958d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
176018a48e76SMat Martineau 
176118a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
176218a48e76SMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
17630a708f8fSGustavo F. Padovan 	}
17640a708f8fSGustavo F. Padovan 
176518a48e76SMat Martineau 	BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
176618a48e76SMat Martineau 	       (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
176718a48e76SMat Martineau 
176818a48e76SMat Martineau 	return sent;
17690a708f8fSGustavo F. Padovan }
17700a708f8fSGustavo F. Padovan 
1771e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1772e1fbd4c1SMat Martineau {
1773e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1774e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1775e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1776e1fbd4c1SMat Martineau 	u16 seq;
1777e1fbd4c1SMat Martineau 
1778e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1779e1fbd4c1SMat Martineau 
1780e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1781e1fbd4c1SMat Martineau 		return;
1782e1fbd4c1SMat Martineau 
1783e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1784e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1785e1fbd4c1SMat Martineau 
1786e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1787e1fbd4c1SMat Martineau 		if (!skb) {
1788e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
1789e1fbd4c1SMat Martineau 				seq);
1790e1fbd4c1SMat Martineau 			continue;
1791e1fbd4c1SMat Martineau 		}
1792e1fbd4c1SMat Martineau 
1793e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
1794e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
1795e1fbd4c1SMat Martineau 
1796e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
1797e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
1798e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
1799e1fbd4c1SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
1800e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1801e1fbd4c1SMat Martineau 			break;
1802e1fbd4c1SMat Martineau 		}
1803e1fbd4c1SMat Martineau 
1804e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
1805e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
1806e1fbd4c1SMat Martineau 			control.final = 1;
1807e1fbd4c1SMat Martineau 		else
1808e1fbd4c1SMat Martineau 			control.final = 0;
1809e1fbd4c1SMat Martineau 
1810e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
1811e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
1812e1fbd4c1SMat Martineau 			 * writeable copy
1813e1fbd4c1SMat Martineau 			 */
1814e1fbd4c1SMat Martineau 			tx_skb = skb_copy(skb, GFP_ATOMIC);
1815e1fbd4c1SMat Martineau 		} else {
1816e1fbd4c1SMat Martineau 			tx_skb = skb_clone(skb, GFP_ATOMIC);
1817e1fbd4c1SMat Martineau 		}
1818e1fbd4c1SMat Martineau 
1819e1fbd4c1SMat Martineau 		if (!tx_skb) {
1820e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1821e1fbd4c1SMat Martineau 			break;
1822e1fbd4c1SMat Martineau 		}
1823e1fbd4c1SMat Martineau 
1824e1fbd4c1SMat Martineau 		/* Update skb contents */
1825e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1826e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
1827e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1828e1fbd4c1SMat Martineau 		} else {
1829e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
1830e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1831e1fbd4c1SMat Martineau 		}
1832e1fbd4c1SMat Martineau 
1833e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
1834e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
1835e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
1836e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
1837e1fbd4c1SMat Martineau 		}
1838e1fbd4c1SMat Martineau 
1839e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
1840e1fbd4c1SMat Martineau 
1841e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
1842e1fbd4c1SMat Martineau 
1843e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
1844e1fbd4c1SMat Martineau 	}
1845e1fbd4c1SMat Martineau }
1846e1fbd4c1SMat Martineau 
1847f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
1848f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
1849f80842a8SMat Martineau {
1850f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1851f80842a8SMat Martineau 
1852f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
1853f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
1854f80842a8SMat Martineau }
1855f80842a8SMat Martineau 
1856d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
1857d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
1858d2a7ac5dSMat Martineau {
1859e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1860e1fbd4c1SMat Martineau 
1861e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1862e1fbd4c1SMat Martineau 
1863e1fbd4c1SMat Martineau 	if (control->poll)
1864e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
1865e1fbd4c1SMat Martineau 
1866e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
1867e1fbd4c1SMat Martineau 
1868e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1869e1fbd4c1SMat Martineau 		return;
1870e1fbd4c1SMat Martineau 
1871e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
1872e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
1873e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
1874e1fbd4c1SMat Martineau 				skb == chan->tx_send_head)
1875e1fbd4c1SMat Martineau 				break;
1876e1fbd4c1SMat Martineau 		}
1877e1fbd4c1SMat Martineau 
1878e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
1879e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
1880e1fbd4c1SMat Martineau 				break;
1881e1fbd4c1SMat Martineau 
1882e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
1883e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
1884e1fbd4c1SMat Martineau 		}
1885e1fbd4c1SMat Martineau 
1886e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
1887e1fbd4c1SMat Martineau 	}
1888d2a7ac5dSMat Martineau }
1889d2a7ac5dSMat Martineau 
1890b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1891b17e73bbSSzymon Janc {
18920a0aba42SMat Martineau 	struct l2cap_ctrl control;
18930a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
18940a0aba42SMat Martineau 					 chan->last_acked_seq);
18950a0aba42SMat Martineau 	int threshold;
18960a0aba42SMat Martineau 
18970a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
18980a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
18990a0aba42SMat Martineau 
19000a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
19010a0aba42SMat Martineau 	control.sframe = 1;
19020a0aba42SMat Martineau 
19030a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
19040a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
1905b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
19060a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
19070a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
19080a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
19090a0aba42SMat Martineau 	} else {
19100a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
19110a0aba42SMat Martineau 			l2cap_ertm_send(chan);
19120a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
19130a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
19140a0aba42SMat Martineau 				frames_to_ack = 0;
19150a0aba42SMat Martineau 		}
19160a0aba42SMat Martineau 
19170a0aba42SMat Martineau 		/* Ack now if the tx window is 3/4ths full.
19180a0aba42SMat Martineau 		 * Calculate without mul or div
19190a0aba42SMat Martineau 		 */
19200a0aba42SMat Martineau 		threshold = chan->tx_win;
19210a0aba42SMat Martineau 		threshold += threshold << 1;
19220a0aba42SMat Martineau 		threshold >>= 2;
19230a0aba42SMat Martineau 
19240a0aba42SMat Martineau 		BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
19250a0aba42SMat Martineau 		       threshold);
19260a0aba42SMat Martineau 
19270a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
19280a0aba42SMat Martineau 			__clear_ack_timer(chan);
19290a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
19300a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
19310a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
19320a0aba42SMat Martineau 			frames_to_ack = 0;
19330a0aba42SMat Martineau 		}
19340a0aba42SMat Martineau 
19350a0aba42SMat Martineau 		if (frames_to_ack)
19360a0aba42SMat Martineau 			__set_ack_timer(chan);
19370a0aba42SMat Martineau 	}
1938b17e73bbSSzymon Janc }
1939b17e73bbSSzymon Janc 
194004124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
194104124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
194204124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
19430a708f8fSGustavo F. Padovan {
19440952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
19450a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
194690338947SGustavo Padovan 	int sent = 0;
19470a708f8fSGustavo F. Padovan 
19480a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
19490a708f8fSGustavo F. Padovan 		return -EFAULT;
19500a708f8fSGustavo F. Padovan 
19510a708f8fSGustavo F. Padovan 	sent += count;
19520a708f8fSGustavo F. Padovan 	len  -= count;
19530a708f8fSGustavo F. Padovan 
19540a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
19550a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
19560a708f8fSGustavo F. Padovan 	while (len) {
1957fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1958fbe00700SGustavo Padovan 
19590a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
19600a708f8fSGustavo F. Padovan 
1961fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
196290338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1963fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1964fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
19652f7719ceSAndrei Emeltchenko 
1966fbe00700SGustavo Padovan 		*frag = tmp;
1967fbe00700SGustavo Padovan 
19680a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
19690a708f8fSGustavo F. Padovan 			return -EFAULT;
19700a708f8fSGustavo F. Padovan 
19715e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
19725e59b791SLuiz Augusto von Dentz 
19730a708f8fSGustavo F. Padovan 		sent += count;
19740a708f8fSGustavo F. Padovan 		len  -= count;
19750a708f8fSGustavo F. Padovan 
19762d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
19772d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
19782d0ed3d5SGustavo Padovan 
19790a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
19800a708f8fSGustavo F. Padovan 	}
19810a708f8fSGustavo F. Padovan 
19820a708f8fSGustavo F. Padovan 	return sent;
19830a708f8fSGustavo F. Padovan }
19840a708f8fSGustavo F. Padovan 
19855e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
19865e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19875e59b791SLuiz Augusto von Dentz 						u32 priority)
19880a708f8fSGustavo F. Padovan {
19898c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19900a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
199103a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
19920a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19930a708f8fSGustavo F. Padovan 
19946d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
19950a708f8fSGustavo F. Padovan 
19960a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19972f7719ceSAndrei Emeltchenko 
19982f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
199990338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
200090338947SGustavo Padovan 	if (IS_ERR(skb))
200190338947SGustavo Padovan 		return skb;
20020a708f8fSGustavo F. Padovan 
20035e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20045e59b791SLuiz Augusto von Dentz 
20050a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20060a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2007fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2008daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
2009daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
20100a708f8fSGustavo F. Padovan 
20110952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20120a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20130a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20140a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20150a708f8fSGustavo F. Padovan 	}
20160a708f8fSGustavo F. Padovan 	return skb;
20170a708f8fSGustavo F. Padovan }
20180a708f8fSGustavo F. Padovan 
20195e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
20205e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
20215e59b791SLuiz Augusto von Dentz 						u32 priority)
20220a708f8fSGustavo F. Padovan {
20238c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20240a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2025f2ba7faeSGustavo Padovan 	int err, count;
20260a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20270a708f8fSGustavo F. Padovan 
20286d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20290a708f8fSGustavo F. Padovan 
2030f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
20312f7719ceSAndrei Emeltchenko 
2032f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
203390338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
203490338947SGustavo Padovan 	if (IS_ERR(skb))
203590338947SGustavo Padovan 		return skb;
20360a708f8fSGustavo F. Padovan 
20375e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20385e59b791SLuiz Augusto von Dentz 
20390a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20400a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2041fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20426ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
20430a708f8fSGustavo F. Padovan 
20440952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20450a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20460a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20470a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20480a708f8fSGustavo F. Padovan 	}
20490a708f8fSGustavo F. Padovan 	return skb;
20500a708f8fSGustavo F. Padovan }
20510a708f8fSGustavo F. Padovan 
2052ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2053ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
205494122bbeSMat Martineau 						u16 sdulen)
20550a708f8fSGustavo F. Padovan {
20568c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20570a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2058e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
20590a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20600a708f8fSGustavo F. Padovan 
20616d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20620a708f8fSGustavo F. Padovan 
20630a708f8fSGustavo F. Padovan 	if (!conn)
20640a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
20650a708f8fSGustavo F. Padovan 
2066e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2067e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
2068e4ca6d98SAndrei Emeltchenko 	else
2069e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
2070e4ca6d98SAndrei Emeltchenko 
20710a708f8fSGustavo F. Padovan 	if (sdulen)
207203a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
20730a708f8fSGustavo F. Padovan 
207447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
207503a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
20760a708f8fSGustavo F. Padovan 
20770a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
20782f7719ceSAndrei Emeltchenko 
20792f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
208090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
208190338947SGustavo Padovan 	if (IS_ERR(skb))
208290338947SGustavo Padovan 		return skb;
20830a708f8fSGustavo F. Padovan 
20840a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20850a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2086fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20870a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
208888843ab0SAndrei Emeltchenko 
208918a48e76SMat Martineau 	/* Control header is populated later */
209018a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
209118a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
209218a48e76SMat Martineau 	else
209318a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
209488843ab0SAndrei Emeltchenko 
20950a708f8fSGustavo F. Padovan 	if (sdulen)
209603a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
20970a708f8fSGustavo F. Padovan 
20980952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20990a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
21000a708f8fSGustavo F. Padovan 		kfree_skb(skb);
21010a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
21020a708f8fSGustavo F. Padovan 	}
21030a708f8fSGustavo F. Padovan 
210418a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
21053ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
21060a708f8fSGustavo F. Padovan 	return skb;
21070a708f8fSGustavo F. Padovan }
21080a708f8fSGustavo F. Padovan 
210994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
211094122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
211194122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
21120a708f8fSGustavo F. Padovan {
21130a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
211494122bbeSMat Martineau 	u16 sdu_len;
211594122bbeSMat Martineau 	size_t pdu_len;
211694122bbeSMat Martineau 	int err = 0;
211794122bbeSMat Martineau 	u8 sar;
21180a708f8fSGustavo F. Padovan 
211994122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
21200a708f8fSGustavo F. Padovan 
212194122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
212294122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
212394122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
212494122bbeSMat Martineau 	 */
212594122bbeSMat Martineau 
212694122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
212794122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
212894122bbeSMat Martineau 
212994122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
213094122bbeSMat Martineau 
213194122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
213294122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
213394122bbeSMat Martineau 
213494122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
213594122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
213694122bbeSMat Martineau 
213794122bbeSMat Martineau 	if (len <= pdu_len) {
213894122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
213994122bbeSMat Martineau 		sdu_len = 0;
214094122bbeSMat Martineau 		pdu_len = len;
214194122bbeSMat Martineau 	} else {
214294122bbeSMat Martineau 		sar = L2CAP_SAR_START;
214394122bbeSMat Martineau 		sdu_len = len;
214494122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
214594122bbeSMat Martineau 	}
21460a708f8fSGustavo F. Padovan 
21470a708f8fSGustavo F. Padovan 	while (len > 0) {
214894122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
21490a708f8fSGustavo F. Padovan 
21500a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
215194122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
21520a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
21530a708f8fSGustavo F. Padovan 		}
21540a708f8fSGustavo F. Padovan 
215594122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
215694122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
21570a708f8fSGustavo F. Padovan 
215894122bbeSMat Martineau 		len -= pdu_len;
215994122bbeSMat Martineau 		if (sdu_len) {
216094122bbeSMat Martineau 			sdu_len = 0;
216194122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
216294122bbeSMat Martineau 		}
216394122bbeSMat Martineau 
216494122bbeSMat Martineau 		if (len <= pdu_len) {
216594122bbeSMat Martineau 			sar = L2CAP_SAR_END;
216694122bbeSMat Martineau 			pdu_len = len;
216794122bbeSMat Martineau 		} else {
216894122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
216994122bbeSMat Martineau 		}
217094122bbeSMat Martineau 	}
217194122bbeSMat Martineau 
217294122bbeSMat Martineau 	return err;
21730a708f8fSGustavo F. Padovan }
21740a708f8fSGustavo F. Padovan 
21755e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
21765e59b791SLuiz Augusto von Dentz 								u32 priority)
21779a91a04aSGustavo F. Padovan {
21789a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
21799a91a04aSGustavo F. Padovan 	int err;
218094122bbeSMat Martineau 	struct sk_buff_head seg_queue;
21819a91a04aSGustavo F. Padovan 
21829a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2183715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
21845e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
21859a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21869a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21879a91a04aSGustavo F. Padovan 
21889a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21899a91a04aSGustavo F. Padovan 		return len;
21909a91a04aSGustavo F. Padovan 	}
21919a91a04aSGustavo F. Padovan 
21929a91a04aSGustavo F. Padovan 	switch (chan->mode) {
21939a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
21949a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
21959a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
21969a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
21979a91a04aSGustavo F. Padovan 
21989a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
21995e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
22009a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
22019a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
22029a91a04aSGustavo F. Padovan 
22039a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
22049a91a04aSGustavo F. Padovan 		err = len;
22059a91a04aSGustavo F. Padovan 		break;
22069a91a04aSGustavo F. Padovan 
22079a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
22089a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
220994122bbeSMat Martineau 		/* Check outgoing MTU */
221094122bbeSMat Martineau 		if (len > chan->omtu) {
221194122bbeSMat Martineau 			err = -EMSGSIZE;
22129a91a04aSGustavo F. Padovan 			break;
22139a91a04aSGustavo F. Padovan 		}
22149a91a04aSGustavo F. Padovan 
221594122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
221694122bbeSMat Martineau 
221794122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
221894122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
221994122bbeSMat Martineau 		 * allocation.
222094122bbeSMat Martineau 		 */
222194122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
222294122bbeSMat Martineau 
222394122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
222494122bbeSMat Martineau 		 * check that it is still connected.
222594122bbeSMat Martineau 		 */
222694122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
222794122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
222894122bbeSMat Martineau 			err = -ENOTCONN;
22299a91a04aSGustavo F. Padovan 		}
22309a91a04aSGustavo F. Padovan 
223194122bbeSMat Martineau 		if (err)
223294122bbeSMat Martineau 			break;
223394122bbeSMat Martineau 
22343733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2235608bcc6dSMat Martineau 			err = l2cap_tx(chan, 0, &seg_queue,
2236608bcc6dSMat Martineau 				       L2CAP_EV_DATA_REQUEST);
22373733937dSMat Martineau 		else
22383733937dSMat Martineau 			err = l2cap_streaming_send(chan, &seg_queue);
223994122bbeSMat Martineau 
2240608bcc6dSMat Martineau 		if (!err)
22419a91a04aSGustavo F. Padovan 			err = len;
22429a91a04aSGustavo F. Padovan 
224394122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
224494122bbeSMat Martineau 		 * seg_queue and need to be purged.
224594122bbeSMat Martineau 		 */
224694122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
22479a91a04aSGustavo F. Padovan 		break;
22489a91a04aSGustavo F. Padovan 
22499a91a04aSGustavo F. Padovan 	default:
22509a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
22519a91a04aSGustavo F. Padovan 		err = -EBADFD;
22529a91a04aSGustavo F. Padovan 	}
22539a91a04aSGustavo F. Padovan 
22549a91a04aSGustavo F. Padovan 	return err;
22559a91a04aSGustavo F. Padovan }
22569a91a04aSGustavo F. Padovan 
2257d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2258d2a7ac5dSMat Martineau {
2259bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2260bed68bdeSMat Martineau 	u16 seq;
2261bed68bdeSMat Martineau 
2262bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2263bed68bdeSMat Martineau 
2264bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2265bed68bdeSMat Martineau 	control.sframe = 1;
2266bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2267bed68bdeSMat Martineau 
2268bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2269bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2270bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2271bed68bdeSMat Martineau 			control.reqseq = seq;
2272bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2273bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2274bed68bdeSMat Martineau 		}
2275bed68bdeSMat Martineau 	}
2276bed68bdeSMat Martineau 
2277bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2278d2a7ac5dSMat Martineau }
2279d2a7ac5dSMat Martineau 
2280d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2281d2a7ac5dSMat Martineau {
2282bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2283bed68bdeSMat Martineau 
2284bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2285bed68bdeSMat Martineau 
2286bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2287bed68bdeSMat Martineau 		return;
2288bed68bdeSMat Martineau 
2289bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2290bed68bdeSMat Martineau 	control.sframe = 1;
2291bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2292bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2293bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2294d2a7ac5dSMat Martineau }
2295d2a7ac5dSMat Martineau 
2296d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2297d2a7ac5dSMat Martineau {
2298bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2299bed68bdeSMat Martineau 	u16 initial_head;
2300bed68bdeSMat Martineau 	u16 seq;
2301bed68bdeSMat Martineau 
2302bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2303bed68bdeSMat Martineau 
2304bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2305bed68bdeSMat Martineau 	control.sframe = 1;
2306bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2307bed68bdeSMat Martineau 
2308bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2309bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2310bed68bdeSMat Martineau 
2311bed68bdeSMat Martineau 	do {
2312bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2313bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2314bed68bdeSMat Martineau 			break;
2315bed68bdeSMat Martineau 
2316bed68bdeSMat Martineau 		control.reqseq = seq;
2317bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2318bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2319bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2320d2a7ac5dSMat Martineau }
2321d2a7ac5dSMat Martineau 
2322608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2323608bcc6dSMat Martineau {
2324608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2325608bcc6dSMat Martineau 	u16 ackseq;
2326608bcc6dSMat Martineau 
2327608bcc6dSMat Martineau 	BT_DBG("chan %p, reqseq %d", chan, reqseq);
2328608bcc6dSMat Martineau 
2329608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2330608bcc6dSMat Martineau 		return;
2331608bcc6dSMat Martineau 
2332608bcc6dSMat Martineau 	BT_DBG("expected_ack_seq %d, unacked_frames %d",
2333608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2334608bcc6dSMat Martineau 
2335608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2336608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2337608bcc6dSMat Martineau 
2338608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2339608bcc6dSMat Martineau 		if (acked_skb) {
2340608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2341608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2342608bcc6dSMat Martineau 			chan->unacked_frames--;
2343608bcc6dSMat Martineau 		}
2344608bcc6dSMat Martineau 	}
2345608bcc6dSMat Martineau 
2346608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2347608bcc6dSMat Martineau 
2348608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2349608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2350608bcc6dSMat Martineau 
2351608bcc6dSMat Martineau 	BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
2352608bcc6dSMat Martineau }
2353608bcc6dSMat Martineau 
2354608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2355608bcc6dSMat Martineau {
2356608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2357608bcc6dSMat Martineau 
2358608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2359608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2360608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2361608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2362608bcc6dSMat Martineau }
2363608bcc6dSMat Martineau 
2364608bcc6dSMat Martineau static int l2cap_tx_state_xmit(struct l2cap_chan *chan,
2365608bcc6dSMat Martineau 			       struct l2cap_ctrl *control,
2366608bcc6dSMat Martineau 			       struct sk_buff_head *skbs, u8 event)
2367608bcc6dSMat Martineau {
2368608bcc6dSMat Martineau 	int err = 0;
2369608bcc6dSMat Martineau 
2370608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2371608bcc6dSMat Martineau 	       event);
2372608bcc6dSMat Martineau 
2373608bcc6dSMat Martineau 	switch (event) {
2374608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2375608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2376608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2377608bcc6dSMat Martineau 
2378608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2379608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2380608bcc6dSMat Martineau 		break;
2381608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2382608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2383608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2384608bcc6dSMat Martineau 
2385608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2386608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2387608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2388608bcc6dSMat Martineau 			 */
2389608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2390608bcc6dSMat Martineau 		}
2391608bcc6dSMat Martineau 
2392608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2393608bcc6dSMat Martineau 
2394608bcc6dSMat Martineau 		break;
2395608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2396608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2397608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2398608bcc6dSMat Martineau 
2399608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2400608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2401608bcc6dSMat Martineau 
2402608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2403608bcc6dSMat Martineau 			local_control.sframe = 1;
2404608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2405608bcc6dSMat Martineau 			local_control.poll = 1;
2406608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2407a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2408608bcc6dSMat Martineau 
2409608bcc6dSMat Martineau 			chan->retry_count = 1;
2410608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2411608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2412608bcc6dSMat Martineau 		}
2413608bcc6dSMat Martineau 		break;
2414608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2415608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2416608bcc6dSMat Martineau 		break;
2417608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2418608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2419608bcc6dSMat Martineau 		chan->retry_count = 1;
2420608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2421608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2422608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2423608bcc6dSMat Martineau 		break;
2424608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2425608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2426608bcc6dSMat Martineau 		chan->retry_count = 1;
2427608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2428608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2429608bcc6dSMat Martineau 		break;
2430608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2431608bcc6dSMat Martineau 		/* Nothing to process */
2432608bcc6dSMat Martineau 		break;
2433608bcc6dSMat Martineau 	default:
2434608bcc6dSMat Martineau 		break;
2435608bcc6dSMat Martineau 	}
2436608bcc6dSMat Martineau 
2437608bcc6dSMat Martineau 	return err;
2438608bcc6dSMat Martineau }
2439608bcc6dSMat Martineau 
2440608bcc6dSMat Martineau static int l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2441608bcc6dSMat Martineau 				 struct l2cap_ctrl *control,
2442608bcc6dSMat Martineau 				 struct sk_buff_head *skbs, u8 event)
2443608bcc6dSMat Martineau {
2444608bcc6dSMat Martineau 	int err = 0;
2445608bcc6dSMat Martineau 
2446608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2447608bcc6dSMat Martineau 	       event);
2448608bcc6dSMat Martineau 
2449608bcc6dSMat Martineau 	switch (event) {
2450608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2451608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2452608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2453608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2454608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2455608bcc6dSMat Martineau 		break;
2456608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2457608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2458608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2459608bcc6dSMat Martineau 
2460608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2461608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2462608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2463608bcc6dSMat Martineau 			 */
2464608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2465608bcc6dSMat Martineau 		}
2466608bcc6dSMat Martineau 
2467608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2468608bcc6dSMat Martineau 
2469608bcc6dSMat Martineau 		break;
2470608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2471608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2472608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2473608bcc6dSMat Martineau 
2474608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2475608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2476608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2477608bcc6dSMat Martineau 			local_control.sframe = 1;
2478608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2479608bcc6dSMat Martineau 			local_control.poll = 1;
2480608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2481a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2482608bcc6dSMat Martineau 
2483608bcc6dSMat Martineau 			chan->retry_count = 1;
2484608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2485608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2486608bcc6dSMat Martineau 		}
2487608bcc6dSMat Martineau 		break;
2488608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2489608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2490608bcc6dSMat Martineau 
2491608bcc6dSMat Martineau 		/* Fall through */
2492608bcc6dSMat Martineau 
2493608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2494608bcc6dSMat Martineau 		if (control && control->final) {
2495608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2496608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2497608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2498608bcc6dSMat Martineau 			chan->retry_count = 0;
2499608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2500608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2501608bcc6dSMat Martineau 		}
2502608bcc6dSMat Martineau 		break;
2503608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2504608bcc6dSMat Martineau 		/* Ignore */
2505608bcc6dSMat Martineau 		break;
2506608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2507608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2508608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2509608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2510608bcc6dSMat Martineau 			chan->retry_count++;
2511608bcc6dSMat Martineau 		} else {
2512608bcc6dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2513608bcc6dSMat Martineau 		}
2514608bcc6dSMat Martineau 		break;
2515608bcc6dSMat Martineau 	default:
2516608bcc6dSMat Martineau 		break;
2517608bcc6dSMat Martineau 	}
2518608bcc6dSMat Martineau 
2519608bcc6dSMat Martineau 	return err;
2520608bcc6dSMat Martineau }
2521608bcc6dSMat Martineau 
2522608bcc6dSMat Martineau static int l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2523608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event)
2524608bcc6dSMat Martineau {
2525608bcc6dSMat Martineau 	int err = 0;
2526608bcc6dSMat Martineau 
2527608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2528608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2529608bcc6dSMat Martineau 
2530608bcc6dSMat Martineau 	switch (chan->tx_state) {
2531608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2532608bcc6dSMat Martineau 		err = l2cap_tx_state_xmit(chan, control, skbs, event);
2533608bcc6dSMat Martineau 		break;
2534608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2535608bcc6dSMat Martineau 		err = l2cap_tx_state_wait_f(chan, control, skbs, event);
2536608bcc6dSMat Martineau 		break;
2537608bcc6dSMat Martineau 	default:
2538608bcc6dSMat Martineau 		/* Ignore event */
2539608bcc6dSMat Martineau 		break;
2540608bcc6dSMat Martineau 	}
2541608bcc6dSMat Martineau 
2542608bcc6dSMat Martineau 	return err;
2543608bcc6dSMat Martineau }
2544608bcc6dSMat Martineau 
25454b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
25464b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
25474b51dae9SMat Martineau {
25484b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
25494b51dae9SMat Martineau 	l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
25504b51dae9SMat Martineau }
25514b51dae9SMat Martineau 
2552f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2553f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2554f80842a8SMat Martineau {
2555f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2556f80842a8SMat Martineau 	l2cap_tx(chan, control, 0, L2CAP_EV_RECV_FBIT);
2557f80842a8SMat Martineau }
2558f80842a8SMat Martineau 
25590a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
25600a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
25610a708f8fSGustavo F. Padovan {
25620a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
256348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
25640a708f8fSGustavo F. Padovan 
25650a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
25660a708f8fSGustavo F. Padovan 
25673df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
25683d57dc68SGustavo F. Padovan 
25693df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
257048454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2571715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
25720a708f8fSGustavo F. Padovan 			continue;
25730a708f8fSGustavo F. Padovan 
25740a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
25750a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
25760a708f8fSGustavo F. Padovan 			continue;
25770a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
25780a708f8fSGustavo F. Padovan 		if (!nskb)
25790a708f8fSGustavo F. Padovan 			continue;
25800a708f8fSGustavo F. Padovan 
258123070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
25820a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
25830a708f8fSGustavo F. Padovan 	}
25843d57dc68SGustavo F. Padovan 
25853df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
25860a708f8fSGustavo F. Padovan }
25870a708f8fSGustavo F. Padovan 
25880a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
25890a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
25900a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
25910a708f8fSGustavo F. Padovan {
25920a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
25930a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
25940a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
25950a708f8fSGustavo F. Padovan 	int len, count;
25960a708f8fSGustavo F. Padovan 
25970a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
25980a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
25990a708f8fSGustavo F. Padovan 
26000a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
26010a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
26020a708f8fSGustavo F. Padovan 
26030a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
26040a708f8fSGustavo F. Padovan 	if (!skb)
26050a708f8fSGustavo F. Padovan 		return NULL;
26060a708f8fSGustavo F. Padovan 
26070a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
26080a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
26093300d9a9SClaudio Takahasi 
26103300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
26113300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
26123300d9a9SClaudio Takahasi 	else
26130a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
26140a708f8fSGustavo F. Padovan 
26150a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
26160a708f8fSGustavo F. Padovan 	cmd->code  = code;
26170a708f8fSGustavo F. Padovan 	cmd->ident = ident;
26180a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
26190a708f8fSGustavo F. Padovan 
26200a708f8fSGustavo F. Padovan 	if (dlen) {
26210a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
26220a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
26230a708f8fSGustavo F. Padovan 		data += count;
26240a708f8fSGustavo F. Padovan 	}
26250a708f8fSGustavo F. Padovan 
26260a708f8fSGustavo F. Padovan 	len -= skb->len;
26270a708f8fSGustavo F. Padovan 
26280a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
26290a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
26300a708f8fSGustavo F. Padovan 	while (len) {
26310a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
26320a708f8fSGustavo F. Padovan 
26330a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
26340a708f8fSGustavo F. Padovan 		if (!*frag)
26350a708f8fSGustavo F. Padovan 			goto fail;
26360a708f8fSGustavo F. Padovan 
26370a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
26380a708f8fSGustavo F. Padovan 
26390a708f8fSGustavo F. Padovan 		len  -= count;
26400a708f8fSGustavo F. Padovan 		data += count;
26410a708f8fSGustavo F. Padovan 
26420a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
26430a708f8fSGustavo F. Padovan 	}
26440a708f8fSGustavo F. Padovan 
26450a708f8fSGustavo F. Padovan 	return skb;
26460a708f8fSGustavo F. Padovan 
26470a708f8fSGustavo F. Padovan fail:
26480a708f8fSGustavo F. Padovan 	kfree_skb(skb);
26490a708f8fSGustavo F. Padovan 	return NULL;
26500a708f8fSGustavo F. Padovan }
26510a708f8fSGustavo F. Padovan 
26520a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
26530a708f8fSGustavo F. Padovan {
26540a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26550a708f8fSGustavo F. Padovan 	int len;
26560a708f8fSGustavo F. Padovan 
26570a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
26580a708f8fSGustavo F. Padovan 	*ptr += len;
26590a708f8fSGustavo F. Padovan 
26600a708f8fSGustavo F. Padovan 	*type = opt->type;
26610a708f8fSGustavo F. Padovan 	*olen = opt->len;
26620a708f8fSGustavo F. Padovan 
26630a708f8fSGustavo F. Padovan 	switch (opt->len) {
26640a708f8fSGustavo F. Padovan 	case 1:
26650a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
26660a708f8fSGustavo F. Padovan 		break;
26670a708f8fSGustavo F. Padovan 
26680a708f8fSGustavo F. Padovan 	case 2:
26690a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
26700a708f8fSGustavo F. Padovan 		break;
26710a708f8fSGustavo F. Padovan 
26720a708f8fSGustavo F. Padovan 	case 4:
26730a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
26740a708f8fSGustavo F. Padovan 		break;
26750a708f8fSGustavo F. Padovan 
26760a708f8fSGustavo F. Padovan 	default:
26770a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
26780a708f8fSGustavo F. Padovan 		break;
26790a708f8fSGustavo F. Padovan 	}
26800a708f8fSGustavo F. Padovan 
26810a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
26820a708f8fSGustavo F. Padovan 	return len;
26830a708f8fSGustavo F. Padovan }
26840a708f8fSGustavo F. Padovan 
26850a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
26860a708f8fSGustavo F. Padovan {
26870a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26880a708f8fSGustavo F. Padovan 
26890a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
26900a708f8fSGustavo F. Padovan 
26910a708f8fSGustavo F. Padovan 	opt->type = type;
26920a708f8fSGustavo F. Padovan 	opt->len  = len;
26930a708f8fSGustavo F. Padovan 
26940a708f8fSGustavo F. Padovan 	switch (len) {
26950a708f8fSGustavo F. Padovan 	case 1:
26960a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
26970a708f8fSGustavo F. Padovan 		break;
26980a708f8fSGustavo F. Padovan 
26990a708f8fSGustavo F. Padovan 	case 2:
27000a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
27010a708f8fSGustavo F. Padovan 		break;
27020a708f8fSGustavo F. Padovan 
27030a708f8fSGustavo F. Padovan 	case 4:
27040a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
27050a708f8fSGustavo F. Padovan 		break;
27060a708f8fSGustavo F. Padovan 
27070a708f8fSGustavo F. Padovan 	default:
27080a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
27090a708f8fSGustavo F. Padovan 		break;
27100a708f8fSGustavo F. Padovan 	}
27110a708f8fSGustavo F. Padovan 
27120a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
27130a708f8fSGustavo F. Padovan }
27140a708f8fSGustavo F. Padovan 
2715f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2716f89cef09SAndrei Emeltchenko {
2717f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2718f89cef09SAndrei Emeltchenko 
2719f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2720f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2721f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2722f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2723f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2724f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2725f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2726f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2727f89cef09SAndrei Emeltchenko 		break;
2728f89cef09SAndrei Emeltchenko 
2729f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2730f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2731f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2732f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2733f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2734f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2735f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2736f89cef09SAndrei Emeltchenko 		break;
2737f89cef09SAndrei Emeltchenko 
2738f89cef09SAndrei Emeltchenko 	default:
2739f89cef09SAndrei Emeltchenko 		return;
2740f89cef09SAndrei Emeltchenko 	}
2741f89cef09SAndrei Emeltchenko 
2742f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2743f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2744f89cef09SAndrei Emeltchenko }
2745f89cef09SAndrei Emeltchenko 
2746721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
27470a708f8fSGustavo F. Padovan {
2748721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2749721c4181SGustavo F. Padovan 							ack_timer.work);
27500a708f8fSGustavo F. Padovan 
27512fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27522fb9b3d4SGustavo F. Padovan 
27536be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
27546be36555SAndrei Emeltchenko 
27550a0aba42SMat Martineau 	l2cap_send_ack(chan);
27566be36555SAndrei Emeltchenko 
27576be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
275809bfb2eeSSzymon Janc 
275909bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
27600a708f8fSGustavo F. Padovan }
27610a708f8fSGustavo F. Padovan 
27623c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
27630a708f8fSGustavo F. Padovan {
27643c588192SMat Martineau 	int err;
27653c588192SMat Martineau 
2766105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2767105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
276842e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
27696a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
277042e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
27716a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2772105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2773105bdf9eSMat Martineau 	chan->sdu = NULL;
2774105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2775105bdf9eSMat Martineau 	chan->sdu_len = 0;
2776105bdf9eSMat Martineau 
2777d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2778d34c34fbSMat Martineau 
2779105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2780105bdf9eSMat Martineau 		return 0;
2781105bdf9eSMat Martineau 
2782105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2783105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
27840a708f8fSGustavo F. Padovan 
2785721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2786721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2787721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
27880a708f8fSGustavo F. Padovan 
2789f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
27900a708f8fSGustavo F. Padovan 
27913c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
27923c588192SMat Martineau 	if (err < 0)
27933c588192SMat Martineau 		return err;
27943c588192SMat Martineau 
27959dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
27969dc9affcSMat Martineau 	if (err < 0)
27979dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
27989dc9affcSMat Martineau 
27999dc9affcSMat Martineau 	return err;
28000a708f8fSGustavo F. Padovan }
28010a708f8fSGustavo F. Padovan 
28020a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
28030a708f8fSGustavo F. Padovan {
28040a708f8fSGustavo F. Padovan 	switch (mode) {
28050a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
28070a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
28080a708f8fSGustavo F. Padovan 			return mode;
28090a708f8fSGustavo F. Padovan 		/* fall through */
28100a708f8fSGustavo F. Padovan 	default:
28110a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
28120a708f8fSGustavo F. Padovan 	}
28130a708f8fSGustavo F. Padovan }
28140a708f8fSGustavo F. Padovan 
28156327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
28166327eb98SAndrei Emeltchenko {
28176327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
28186327eb98SAndrei Emeltchenko }
28196327eb98SAndrei Emeltchenko 
2820f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2821f89cef09SAndrei Emeltchenko {
2822f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2823f89cef09SAndrei Emeltchenko }
2824f89cef09SAndrei Emeltchenko 
28256327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
28266327eb98SAndrei Emeltchenko {
28276327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2828836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
28296327eb98SAndrei Emeltchenko 		/* use extended control field */
28306327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2831836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2832836be934SAndrei Emeltchenko 	} else {
28336327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
28346327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2835836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2836836be934SAndrei Emeltchenko 	}
28376327eb98SAndrei Emeltchenko }
28386327eb98SAndrei Emeltchenko 
2839710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
28400a708f8fSGustavo F. Padovan {
28410a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
28420c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
28430a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2844c8f79162SAndrei Emeltchenko 	u16 size;
28450a708f8fSGustavo F. Padovan 
284649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
28470a708f8fSGustavo F. Padovan 
284873ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
28490a708f8fSGustavo F. Padovan 		goto done;
28500a708f8fSGustavo F. Padovan 
28510c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28520a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28530a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2854c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
28550a708f8fSGustavo F. Padovan 			break;
28560a708f8fSGustavo F. Padovan 
2857f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2858f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2859f89cef09SAndrei Emeltchenko 
28600a708f8fSGustavo F. Padovan 		/* fall through */
28610a708f8fSGustavo F. Padovan 	default:
28628c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
28630a708f8fSGustavo F. Padovan 		break;
28640a708f8fSGustavo F. Padovan 	}
28650a708f8fSGustavo F. Padovan 
28660a708f8fSGustavo F. Padovan done:
28670c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
28680c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
28690a708f8fSGustavo F. Padovan 
28700c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28710a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
28728c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
28738c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
28740a708f8fSGustavo F. Padovan 			break;
28750a708f8fSGustavo F. Padovan 
28760a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
28770a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
28780a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
28790a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28800a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
28810a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
28820a708f8fSGustavo F. Padovan 
28830a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28840a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28850a708f8fSGustavo F. Padovan 		break;
28860a708f8fSGustavo F. Padovan 
28870a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
28880a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
288947d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
28900a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28910a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2892c8f79162SAndrei Emeltchenko 
2893c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2894c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2895c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2896c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2897c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
28980a708f8fSGustavo F. Padovan 
28996327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
29006327eb98SAndrei Emeltchenko 
29016327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
29026327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
29030a708f8fSGustavo F. Padovan 
29040a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
29050a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
29060a708f8fSGustavo F. Padovan 
2907f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2908f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2909f89cef09SAndrei Emeltchenko 
29108c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29110a708f8fSGustavo F. Padovan 			break;
29120a708f8fSGustavo F. Padovan 
291347d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2914c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
291547d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
291647d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29170a708f8fSGustavo F. Padovan 		}
29186327eb98SAndrei Emeltchenko 
29196327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
29206327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
29216327eb98SAndrei Emeltchenko 								chan->tx_win);
29220a708f8fSGustavo F. Padovan 		break;
29230a708f8fSGustavo F. Padovan 
29240a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
29250a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
29260a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
29270a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
29280a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
29290a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2930c8f79162SAndrei Emeltchenko 
2931c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2932c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2933c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2934c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2935c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
29360a708f8fSGustavo F. Padovan 
29370a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
29380a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
29390a708f8fSGustavo F. Padovan 
2940f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2941f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2942f89cef09SAndrei Emeltchenko 
29438c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29440a708f8fSGustavo F. Padovan 			break;
29450a708f8fSGustavo F. Padovan 
294647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2947c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
294847d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
294947d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29500a708f8fSGustavo F. Padovan 		}
29510a708f8fSGustavo F. Padovan 		break;
29520a708f8fSGustavo F. Padovan 	}
29530a708f8fSGustavo F. Padovan 
2954fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
29550a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
29560a708f8fSGustavo F. Padovan 
29570a708f8fSGustavo F. Padovan 	return ptr - data;
29580a708f8fSGustavo F. Padovan }
29590a708f8fSGustavo F. Padovan 
296073ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
29610a708f8fSGustavo F. Padovan {
29620a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
29630a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
296473ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
296573ffa904SGustavo F. Padovan 	int len = chan->conf_len;
29660a708f8fSGustavo F. Padovan 	int type, hint, olen;
29670a708f8fSGustavo F. Padovan 	unsigned long val;
29680a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
296942dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
297042dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
29710a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
29720a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2973c8f79162SAndrei Emeltchenko 	u16 size;
29740a708f8fSGustavo F. Padovan 
297573ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
29760a708f8fSGustavo F. Padovan 
29770a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29780a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
29790a708f8fSGustavo F. Padovan 
29800a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
29810a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
29820a708f8fSGustavo F. Padovan 
29830a708f8fSGustavo F. Padovan 		switch (type) {
29840a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
29850a708f8fSGustavo F. Padovan 			mtu = val;
29860a708f8fSGustavo F. Padovan 			break;
29870a708f8fSGustavo F. Padovan 
29880a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
29890c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
29900a708f8fSGustavo F. Padovan 			break;
29910a708f8fSGustavo F. Padovan 
29920a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
29930a708f8fSGustavo F. Padovan 			break;
29940a708f8fSGustavo F. Padovan 
29950a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29960a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29970a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
29980a708f8fSGustavo F. Padovan 			break;
29990a708f8fSGustavo F. Padovan 
30000a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
30010a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3002c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
300342dceae2SAndrei Emeltchenko 			break;
30040a708f8fSGustavo F. Padovan 
300542dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
300642dceae2SAndrei Emeltchenko 			remote_efs = 1;
300742dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
300842dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
30090a708f8fSGustavo F. Padovan 			break;
30100a708f8fSGustavo F. Padovan 
30116327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
30126327eb98SAndrei Emeltchenko 			if (!enable_hs)
30136327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
30146327eb98SAndrei Emeltchenko 
30156327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
30166327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3017836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
30186327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
30190a708f8fSGustavo F. Padovan 			break;
30200a708f8fSGustavo F. Padovan 
30210a708f8fSGustavo F. Padovan 		default:
30220a708f8fSGustavo F. Padovan 			if (hint)
30230a708f8fSGustavo F. Padovan 				break;
30240a708f8fSGustavo F. Padovan 
30250a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
30260a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
30270a708f8fSGustavo F. Padovan 			break;
30280a708f8fSGustavo F. Padovan 		}
30290a708f8fSGustavo F. Padovan 	}
30300a708f8fSGustavo F. Padovan 
303173ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
30320a708f8fSGustavo F. Padovan 		goto done;
30330a708f8fSGustavo F. Padovan 
30340c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
30350a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
30360a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3037c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
30380c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
30398c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
30400a708f8fSGustavo F. Padovan 			break;
30410a708f8fSGustavo F. Padovan 		}
30420a708f8fSGustavo F. Padovan 
304342dceae2SAndrei Emeltchenko 		if (remote_efs) {
304442dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
304542dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
304642dceae2SAndrei Emeltchenko 			else
304742dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
304842dceae2SAndrei Emeltchenko 		}
304942dceae2SAndrei Emeltchenko 
30500c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
30510a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30520a708f8fSGustavo F. Padovan 
30530a708f8fSGustavo F. Padovan 		break;
30540a708f8fSGustavo F. Padovan 	}
30550a708f8fSGustavo F. Padovan 
30560a708f8fSGustavo F. Padovan done:
30570c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
30580a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
30590c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
30600a708f8fSGustavo F. Padovan 
306173ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
30620a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30630a708f8fSGustavo F. Padovan 
30640a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
30650a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
30660a708f8fSGustavo F. Padovan 	}
30670a708f8fSGustavo F. Padovan 
30680a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
30690a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
30700a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
30710a708f8fSGustavo F. Padovan 
30720a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
30730a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
30740a708f8fSGustavo F. Padovan 		else {
30750c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3076c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
30770a708f8fSGustavo F. Padovan 		}
30780c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
30790a708f8fSGustavo F. Padovan 
308042dceae2SAndrei Emeltchenko 		if (remote_efs) {
308142dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
308242dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
308342dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
308442dceae2SAndrei Emeltchenko 
308542dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
308642dceae2SAndrei Emeltchenko 
308742dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
308842dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
308942dceae2SAndrei Emeltchenko 
309042dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
309142dceae2SAndrei Emeltchenko 							sizeof(efs),
309242dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
30930e8b207eSAndrei Emeltchenko 			} else {
30943e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
30950e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
30960e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
309742dceae2SAndrei Emeltchenko 			}
309842dceae2SAndrei Emeltchenko 		}
309942dceae2SAndrei Emeltchenko 
31000a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
31010a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
310247d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3103c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31040a708f8fSGustavo F. Padovan 			break;
31050a708f8fSGustavo F. Padovan 
31060a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
31076327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
31082c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
31096327eb98SAndrei Emeltchenko 			else
31106327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
31116327eb98SAndrei Emeltchenko 
31122c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
31130a708f8fSGustavo F. Padovan 
3114c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3115c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3116c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3117c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3118c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3119c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3120c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31210a708f8fSGustavo F. Padovan 
31220a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
31234fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
31240a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
31254fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
31260a708f8fSGustavo F. Padovan 
3127c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31280a708f8fSGustavo F. Padovan 
31290a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31300a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31310a708f8fSGustavo F. Padovan 
313242dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
313342dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
313442dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
313542dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
313642dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
313742dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
313842dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
313942dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
314042dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
314142dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
314242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
314342dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
314442dceae2SAndrei Emeltchenko 			}
31450a708f8fSGustavo F. Padovan 			break;
31460a708f8fSGustavo F. Padovan 
31470a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3148c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3149c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3150c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3151c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3152c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3153c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3154c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31550a708f8fSGustavo F. Padovan 
3156c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31570a708f8fSGustavo F. Padovan 
31580a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31590a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31600a708f8fSGustavo F. Padovan 
31610a708f8fSGustavo F. Padovan 			break;
31620a708f8fSGustavo F. Padovan 
31630a708f8fSGustavo F. Padovan 		default:
31640a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
31650a708f8fSGustavo F. Padovan 
31660a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
31670c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
31680a708f8fSGustavo F. Padovan 		}
31690a708f8fSGustavo F. Padovan 
31700a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3171c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
31720a708f8fSGustavo F. Padovan 	}
3173fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
31740a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
31750a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
31760a708f8fSGustavo F. Padovan 
31770a708f8fSGustavo F. Padovan 	return ptr - data;
31780a708f8fSGustavo F. Padovan }
31790a708f8fSGustavo F. Padovan 
3180b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
31810a708f8fSGustavo F. Padovan {
31820a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
31830a708f8fSGustavo F. Padovan 	void *ptr = req->data;
31840a708f8fSGustavo F. Padovan 	int type, olen;
31850a708f8fSGustavo F. Padovan 	unsigned long val;
318636e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
318766af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
31880a708f8fSGustavo F. Padovan 
3189fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
31900a708f8fSGustavo F. Padovan 
31910a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
31920a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
31930a708f8fSGustavo F. Padovan 
31940a708f8fSGustavo F. Padovan 		switch (type) {
31950a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
31960a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
31970a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
31980c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
31990a708f8fSGustavo F. Padovan 			} else
32000c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
32010c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
32020a708f8fSGustavo F. Padovan 			break;
32030a708f8fSGustavo F. Padovan 
32040a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
32050c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
32060a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
32070c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
32080a708f8fSGustavo F. Padovan 			break;
32090a708f8fSGustavo F. Padovan 
32100a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
32110a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
32120a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
32130a708f8fSGustavo F. Padovan 
3214c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
32150c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
32160a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
32170a708f8fSGustavo F. Padovan 
321847d1ec61SGustavo F. Padovan 			chan->fcs = 0;
32190a708f8fSGustavo F. Padovan 
32200a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
32210a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
32220a708f8fSGustavo F. Padovan 			break;
32236327eb98SAndrei Emeltchenko 
32246327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
32256327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
32266327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
32273e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
32283e6b3b95SGustavo F. Padovan 							chan->tx_win);
32296327eb98SAndrei Emeltchenko 			break;
323066af7aafSAndrei Emeltchenko 
323166af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
323266af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
323366af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
323466af7aafSAndrei Emeltchenko 
323566af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
323666af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
323766af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
323866af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
323966af7aafSAndrei Emeltchenko 
324066af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
324166af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
324266af7aafSAndrei Emeltchenko 			break;
32430a708f8fSGustavo F. Padovan 		}
32440a708f8fSGustavo F. Padovan 	}
32450a708f8fSGustavo F. Padovan 
32460c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
32470a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
32480a708f8fSGustavo F. Padovan 
32490c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
32500a708f8fSGustavo F. Padovan 
32510e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
32520a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
32530a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
325447d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
325547d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
325647d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
325766af7aafSAndrei Emeltchenko 
325866af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
325966af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
326066af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
326166af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
326266af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
326366af7aafSAndrei Emeltchenko 				chan->local_flush_to =
326466af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
326566af7aafSAndrei Emeltchenko 			}
32660a708f8fSGustavo F. Padovan 			break;
326766af7aafSAndrei Emeltchenko 
32680a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
326947d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
32700a708f8fSGustavo F. Padovan 		}
32710a708f8fSGustavo F. Padovan 	}
32720a708f8fSGustavo F. Padovan 
3273fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
32740a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
32750a708f8fSGustavo F. Padovan 
32760a708f8fSGustavo F. Padovan 	return ptr - data;
32770a708f8fSGustavo F. Padovan }
32780a708f8fSGustavo F. Padovan 
3279fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
32800a708f8fSGustavo F. Padovan {
32810a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
32820a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
32830a708f8fSGustavo F. Padovan 
3284fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32850a708f8fSGustavo F. Padovan 
3286fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
32870a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
32880a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
32890a708f8fSGustavo F. Padovan 
32900a708f8fSGustavo F. Padovan 	return ptr - data;
32910a708f8fSGustavo F. Padovan }
32920a708f8fSGustavo F. Padovan 
32938c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3294710f9b0aSGustavo F. Padovan {
3295710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
32968c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3297710f9b0aSGustavo F. Padovan 	u8 buf[128];
3298710f9b0aSGustavo F. Padovan 
3299fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3300fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3301710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3302710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3303710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
3304710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3305710f9b0aSGustavo F. Padovan 
3306c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3307710f9b0aSGustavo F. Padovan 		return;
3308710f9b0aSGustavo F. Padovan 
3309710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3310710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
3311710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3312710f9b0aSGustavo F. Padovan }
3313710f9b0aSGustavo F. Padovan 
331447d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
33150a708f8fSGustavo F. Padovan {
33160a708f8fSGustavo F. Padovan 	int type, olen;
33170a708f8fSGustavo F. Padovan 	unsigned long val;
33180a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
33190a708f8fSGustavo F. Padovan 
332047d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
33210a708f8fSGustavo F. Padovan 
33220c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
33230a708f8fSGustavo F. Padovan 		return;
33240a708f8fSGustavo F. Padovan 
33250a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33260a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
33270a708f8fSGustavo F. Padovan 
33280a708f8fSGustavo F. Padovan 		switch (type) {
33290a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
33300a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
33310a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
33320a708f8fSGustavo F. Padovan 			goto done;
33330a708f8fSGustavo F. Padovan 		}
33340a708f8fSGustavo F. Padovan 	}
33350a708f8fSGustavo F. Padovan 
333636e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
333736e999a8SMat Martineau 	 * did not send an RFC option.
333836e999a8SMat Martineau 	 */
333936e999a8SMat Martineau 	rfc.mode = chan->mode;
334036e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
334136e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
334236e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
334336e999a8SMat Martineau 
334436e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
334536e999a8SMat Martineau 
33460a708f8fSGustavo F. Padovan done:
33470a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
33480a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
334947d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
335047d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
335147d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33520a708f8fSGustavo F. Padovan 		break;
33530a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
335447d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33550a708f8fSGustavo F. Padovan 	}
33560a708f8fSGustavo F. Padovan }
33570a708f8fSGustavo F. Padovan 
33580a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33590a708f8fSGustavo F. Padovan {
3360e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
33610a708f8fSGustavo F. Padovan 
3362e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
33630a708f8fSGustavo F. Padovan 		return 0;
33640a708f8fSGustavo F. Padovan 
33650a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
33660a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
336717cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
33680a708f8fSGustavo F. Padovan 
33690a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
33700a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
33710a708f8fSGustavo F. Padovan 
33720a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
33730a708f8fSGustavo F. Padovan 	}
33740a708f8fSGustavo F. Padovan 
33750a708f8fSGustavo F. Padovan 	return 0;
33760a708f8fSGustavo F. Padovan }
33770a708f8fSGustavo F. Padovan 
33780a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33790a708f8fSGustavo F. Padovan {
33800a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
33810a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
338223691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
33830a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
33840a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
33850a708f8fSGustavo F. Padovan 
33860a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
33870a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
33880a708f8fSGustavo F. Padovan 
3389097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
33900a708f8fSGustavo F. Padovan 
33910a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
3392c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
339323691d75SGustavo F. Padovan 	if (!pchan) {
33940a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
33950a708f8fSGustavo F. Padovan 		goto sendresp;
33960a708f8fSGustavo F. Padovan 	}
33970a708f8fSGustavo F. Padovan 
339823691d75SGustavo F. Padovan 	parent = pchan->sk;
339923691d75SGustavo F. Padovan 
34003df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3401aa2ac881SGustavo F. Padovan 	lock_sock(parent);
34020a708f8fSGustavo F. Padovan 
34030a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
34040a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
34050a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
34069f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
34070a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
34080a708f8fSGustavo F. Padovan 		goto response;
34090a708f8fSGustavo F. Padovan 	}
34100a708f8fSGustavo F. Padovan 
34110a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
34120a708f8fSGustavo F. Padovan 
34130a708f8fSGustavo F. Padovan 	/* Check for backlog size */
34140a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
34150a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
34160a708f8fSGustavo F. Padovan 		goto response;
34170a708f8fSGustavo F. Padovan 	}
34180a708f8fSGustavo F. Padovan 
341980808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
342080808e43SGustavo F. Padovan 	if (!chan)
34210a708f8fSGustavo F. Padovan 		goto response;
34220a708f8fSGustavo F. Padovan 
342380808e43SGustavo F. Padovan 	sk = chan->sk;
342480808e43SGustavo F. Padovan 
34250a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3426baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
34270a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3428ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
34290a708f8fSGustavo F. Padovan 		goto response;
34300a708f8fSGustavo F. Padovan 	}
34310a708f8fSGustavo F. Padovan 
34320a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
34330a708f8fSGustavo F. Padovan 
34340a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
34350a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3436fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3437fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
34380a708f8fSGustavo F. Padovan 
3439d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3440d1010240SGustavo F. Padovan 
34416be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
344248454079SGustavo F. Padovan 
3443fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
34440a708f8fSGustavo F. Padovan 
3445c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
34460a708f8fSGustavo F. Padovan 
3447fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
34480a708f8fSGustavo F. Padovan 
34490a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3450d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3451c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
34520e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
34530a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
34540a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
34550a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
34560a708f8fSGustavo F. Padovan 			} else {
34570e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
34580a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
34590a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
34600a708f8fSGustavo F. Padovan 			}
34610a708f8fSGustavo F. Padovan 		} else {
34620e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
34630a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
34640a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
34650a708f8fSGustavo F. Padovan 		}
34660a708f8fSGustavo F. Padovan 	} else {
34670e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
34680a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
34690a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
34700a708f8fSGustavo F. Padovan 	}
34710a708f8fSGustavo F. Padovan 
34720a708f8fSGustavo F. Padovan response:
3473aa2ac881SGustavo F. Padovan 	release_sock(parent);
34743df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34750a708f8fSGustavo F. Padovan 
34760a708f8fSGustavo F. Padovan sendresp:
34770a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
34780a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
34790a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
34800a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
34810a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
34820a708f8fSGustavo F. Padovan 
34830a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
34840a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
34850a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34860a708f8fSGustavo F. Padovan 
34870a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
34880a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
34890a708f8fSGustavo F. Padovan 
3490ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
34910a708f8fSGustavo F. Padovan 
34920a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
34930a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
34940a708f8fSGustavo F. Padovan 	}
34950a708f8fSGustavo F. Padovan 
3496c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
34970a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
34980a708f8fSGustavo F. Padovan 		u8 buf[128];
3499c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
35000a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
350173ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
350273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
35030a708f8fSGustavo F. Padovan 	}
35040a708f8fSGustavo F. Padovan 
35050a708f8fSGustavo F. Padovan 	return 0;
35060a708f8fSGustavo F. Padovan }
35070a708f8fSGustavo F. Padovan 
35080a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
35090a708f8fSGustavo F. Padovan {
35100a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
35110a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
351248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35130a708f8fSGustavo F. Padovan 	u8 req[128];
35143df91ea2SAndrei Emeltchenko 	int err;
35150a708f8fSGustavo F. Padovan 
35160a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
35170a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
35180a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
35190a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
35200a708f8fSGustavo F. Padovan 
35211b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
35221b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
35230a708f8fSGustavo F. Padovan 
35243df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
35253df91ea2SAndrei Emeltchenko 
35260a708f8fSGustavo F. Padovan 	if (scid) {
35273df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
35283df91ea2SAndrei Emeltchenko 		if (!chan) {
35293df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35303df91ea2SAndrei Emeltchenko 			goto unlock;
35313df91ea2SAndrei Emeltchenko 		}
35320a708f8fSGustavo F. Padovan 	} else {
35333df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
35343df91ea2SAndrei Emeltchenko 		if (!chan) {
35353df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35363df91ea2SAndrei Emeltchenko 			goto unlock;
35373df91ea2SAndrei Emeltchenko 		}
35380a708f8fSGustavo F. Padovan 	}
35390a708f8fSGustavo F. Padovan 
35403df91ea2SAndrei Emeltchenko 	err = 0;
35413df91ea2SAndrei Emeltchenko 
35426be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
354348454079SGustavo F. Padovan 
35440a708f8fSGustavo F. Padovan 	switch (result) {
35450a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
354689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3547fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3548fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3549c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
35500a708f8fSGustavo F. Padovan 
3551c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
35520a708f8fSGustavo F. Padovan 			break;
35530a708f8fSGustavo F. Padovan 
35540a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
355573ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
355673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
35570a708f8fSGustavo F. Padovan 		break;
35580a708f8fSGustavo F. Padovan 
35590a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3560c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
35610a708f8fSGustavo F. Padovan 		break;
35620a708f8fSGustavo F. Padovan 
35630a708f8fSGustavo F. Padovan 	default:
356448454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
35650a708f8fSGustavo F. Padovan 		break;
35660a708f8fSGustavo F. Padovan 	}
35670a708f8fSGustavo F. Padovan 
35686be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
35693df91ea2SAndrei Emeltchenko 
35703df91ea2SAndrei Emeltchenko unlock:
35713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
35723df91ea2SAndrei Emeltchenko 
35733df91ea2SAndrei Emeltchenko 	return err;
35740a708f8fSGustavo F. Padovan }
35750a708f8fSGustavo F. Padovan 
357647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
35770a708f8fSGustavo F. Padovan {
35780a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
35790a708f8fSGustavo F. Padovan 	 * sides request it.
35800a708f8fSGustavo F. Padovan 	 */
35810c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
358247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3583c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
358447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
35850a708f8fSGustavo F. Padovan }
35860a708f8fSGustavo F. Padovan 
35870a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
35880a708f8fSGustavo F. Padovan {
35890a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
35900a708f8fSGustavo F. Padovan 	u16 dcid, flags;
35910a708f8fSGustavo F. Padovan 	u8 rsp[64];
359248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35933c588192SMat Martineau 	int len, err = 0;
35940a708f8fSGustavo F. Padovan 
35950a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
35960a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
35970a708f8fSGustavo F. Padovan 
35980a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
35990a708f8fSGustavo F. Padovan 
3600baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
360148454079SGustavo F. Padovan 	if (!chan)
36020a708f8fSGustavo F. Padovan 		return -ENOENT;
36030a708f8fSGustavo F. Padovan 
3604033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3605e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
36060a708f8fSGustavo F. Padovan 
3607e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3608e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3609e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3610e2fd318eSIlia Kolomisnky 
36110a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
36120a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
36130a708f8fSGustavo F. Padovan 		goto unlock;
36140a708f8fSGustavo F. Padovan 	}
36150a708f8fSGustavo F. Padovan 
36160a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
36170a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
36187ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
36190a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3620fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36210a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
36220a708f8fSGustavo F. Padovan 		goto unlock;
36230a708f8fSGustavo F. Padovan 	}
36240a708f8fSGustavo F. Padovan 
36250a708f8fSGustavo F. Padovan 	/* Store config. */
362673ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
362773ffa904SGustavo F. Padovan 	chan->conf_len += len;
36280a708f8fSGustavo F. Padovan 
36290a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
36300a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
36310a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3632fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36330a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
36340a708f8fSGustavo F. Padovan 		goto unlock;
36350a708f8fSGustavo F. Padovan 	}
36360a708f8fSGustavo F. Padovan 
36370a708f8fSGustavo F. Padovan 	/* Complete config. */
363873ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
36390a708f8fSGustavo F. Padovan 	if (len < 0) {
3640e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
36410a708f8fSGustavo F. Padovan 		goto unlock;
36420a708f8fSGustavo F. Padovan 	}
36430a708f8fSGustavo F. Padovan 
36440a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
364573ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
36460a708f8fSGustavo F. Padovan 
36470a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
364873ffa904SGustavo F. Padovan 	chan->conf_len = 0;
36490a708f8fSGustavo F. Padovan 
3650c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
36510a708f8fSGustavo F. Padovan 		goto unlock;
36520a708f8fSGustavo F. Padovan 
3653c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
365447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
36550a708f8fSGustavo F. Padovan 
365689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
36570a708f8fSGustavo F. Padovan 
3658105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3659105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
36603c588192SMat Martineau 			err = l2cap_ertm_init(chan);
36610a708f8fSGustavo F. Padovan 
36623c588192SMat Martineau 		if (err < 0)
36633c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
36643c588192SMat Martineau 		else
3665cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
36663c588192SMat Martineau 
36670a708f8fSGustavo F. Padovan 		goto unlock;
36680a708f8fSGustavo F. Padovan 	}
36690a708f8fSGustavo F. Padovan 
3670c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
36710a708f8fSGustavo F. Padovan 		u8 buf[64];
36720a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
367373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
367473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
36750a708f8fSGustavo F. Padovan 	}
36760a708f8fSGustavo F. Padovan 
36770e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
36780e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
36790e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
36800e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
36810e8b207eSAndrei Emeltchenko 
36820e8b207eSAndrei Emeltchenko 		/* check compatibility */
36830e8b207eSAndrei Emeltchenko 
36840e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
36850e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
36860e8b207eSAndrei Emeltchenko 
36870e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
36880e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
36890e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
36900e8b207eSAndrei Emeltchenko 	}
36910e8b207eSAndrei Emeltchenko 
36920a708f8fSGustavo F. Padovan unlock:
36936be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36943c588192SMat Martineau 	return err;
36950a708f8fSGustavo F. Padovan }
36960a708f8fSGustavo F. Padovan 
36970a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36980a708f8fSGustavo F. Padovan {
36990a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
37000a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
370148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
370261386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
37033c588192SMat Martineau 	int err = 0;
37040a708f8fSGustavo F. Padovan 
37050a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
37060a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
37070a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
37080a708f8fSGustavo F. Padovan 
370961386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
371061386cbaSAndrei Emeltchenko 	       result, len);
37110a708f8fSGustavo F. Padovan 
3712baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
371348454079SGustavo F. Padovan 	if (!chan)
37140a708f8fSGustavo F. Padovan 		return 0;
37150a708f8fSGustavo F. Padovan 
37160a708f8fSGustavo F. Padovan 	switch (result) {
37170a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
371847d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
37190e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
37200a708f8fSGustavo F. Padovan 		break;
37210a708f8fSGustavo F. Padovan 
37220e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
37230e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
37240e8b207eSAndrei Emeltchenko 
37250e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
37260e8b207eSAndrei Emeltchenko 			char buf[64];
37270e8b207eSAndrei Emeltchenko 
37280e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
37290e8b207eSAndrei Emeltchenko 								buf, &result);
37300e8b207eSAndrei Emeltchenko 			if (len < 0) {
37310e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37320e8b207eSAndrei Emeltchenko 				goto done;
37330e8b207eSAndrei Emeltchenko 			}
37340e8b207eSAndrei Emeltchenko 
37350e8b207eSAndrei Emeltchenko 			/* check compatibility */
37360e8b207eSAndrei Emeltchenko 
37370e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
37380e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37390e8b207eSAndrei Emeltchenko 
37400e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
37410e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
37420e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
37430e8b207eSAndrei Emeltchenko 		}
37440e8b207eSAndrei Emeltchenko 		goto done;
37450e8b207eSAndrei Emeltchenko 
37460a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
374773ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
37480a708f8fSGustavo F. Padovan 			char req[64];
37490a708f8fSGustavo F. Padovan 
37500a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3751e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37520a708f8fSGustavo F. Padovan 				goto done;
37530a708f8fSGustavo F. Padovan 			}
37540a708f8fSGustavo F. Padovan 
37550a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
37560a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3757b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3758b4450035SGustavo F. Padovan 								req, &result);
37590a708f8fSGustavo F. Padovan 			if (len < 0) {
3760e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37610a708f8fSGustavo F. Padovan 				goto done;
37620a708f8fSGustavo F. Padovan 			}
37630a708f8fSGustavo F. Padovan 
37640a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
37650a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
376673ffa904SGustavo F. Padovan 			chan->num_conf_req++;
37670a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
37680a708f8fSGustavo F. Padovan 				goto done;
37690a708f8fSGustavo F. Padovan 			break;
37700a708f8fSGustavo F. Padovan 		}
37710a708f8fSGustavo F. Padovan 
37720a708f8fSGustavo F. Padovan 	default:
37736be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
37742e0052e4SAndrei Emeltchenko 
3775ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3776e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
37770a708f8fSGustavo F. Padovan 		goto done;
37780a708f8fSGustavo F. Padovan 	}
37790a708f8fSGustavo F. Padovan 
37800a708f8fSGustavo F. Padovan 	if (flags & 0x01)
37810a708f8fSGustavo F. Padovan 		goto done;
37820a708f8fSGustavo F. Padovan 
3783c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
37840a708f8fSGustavo F. Padovan 
3785c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
378647d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
37870a708f8fSGustavo F. Padovan 
378889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3789105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3790105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
37913c588192SMat Martineau 			err = l2cap_ertm_init(chan);
37920a708f8fSGustavo F. Padovan 
37933c588192SMat Martineau 		if (err < 0)
37943c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
37953c588192SMat Martineau 		else
3796cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
37970a708f8fSGustavo F. Padovan 	}
37980a708f8fSGustavo F. Padovan 
37990a708f8fSGustavo F. Padovan done:
38006be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38013c588192SMat Martineau 	return err;
38020a708f8fSGustavo F. Padovan }
38030a708f8fSGustavo F. Padovan 
38040a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38050a708f8fSGustavo F. Padovan {
38060a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
38070a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
38080a708f8fSGustavo F. Padovan 	u16 dcid, scid;
380948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38100a708f8fSGustavo F. Padovan 	struct sock *sk;
38110a708f8fSGustavo F. Padovan 
38120a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
38130a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
38140a708f8fSGustavo F. Padovan 
38150a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
38160a708f8fSGustavo F. Padovan 
38173df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38183df91ea2SAndrei Emeltchenko 
38193df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
38203df91ea2SAndrei Emeltchenko 	if (!chan) {
38213df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38220a708f8fSGustavo F. Padovan 		return 0;
38233df91ea2SAndrei Emeltchenko 	}
38240a708f8fSGustavo F. Padovan 
38256be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
38266be36555SAndrei Emeltchenko 
382748454079SGustavo F. Padovan 	sk = chan->sk;
382848454079SGustavo F. Padovan 
3829fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3830fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
38310a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
38320a708f8fSGustavo F. Padovan 
38336be36555SAndrei Emeltchenko 	lock_sock(sk);
38340a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
38356be36555SAndrei Emeltchenko 	release_sock(sk);
38360a708f8fSGustavo F. Padovan 
383761d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
383848454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
38396be36555SAndrei Emeltchenko 
38406be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38410a708f8fSGustavo F. Padovan 
3842ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
384361d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38443df91ea2SAndrei Emeltchenko 
38453df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38463df91ea2SAndrei Emeltchenko 
38470a708f8fSGustavo F. Padovan 	return 0;
38480a708f8fSGustavo F. Padovan }
38490a708f8fSGustavo F. Padovan 
38500a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38510a708f8fSGustavo F. Padovan {
38520a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
38530a708f8fSGustavo F. Padovan 	u16 dcid, scid;
385448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38550a708f8fSGustavo F. Padovan 
38560a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
38570a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
38580a708f8fSGustavo F. Padovan 
38590a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
38600a708f8fSGustavo F. Padovan 
38613df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38623df91ea2SAndrei Emeltchenko 
38633df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
38643df91ea2SAndrei Emeltchenko 	if (!chan) {
38653df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38660a708f8fSGustavo F. Padovan 		return 0;
38673df91ea2SAndrei Emeltchenko 	}
38680a708f8fSGustavo F. Padovan 
38696be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
387048454079SGustavo F. Padovan 
387161d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
387248454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
38736be36555SAndrei Emeltchenko 
38746be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38750a708f8fSGustavo F. Padovan 
3876ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
387761d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38783df91ea2SAndrei Emeltchenko 
38793df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38803df91ea2SAndrei Emeltchenko 
38810a708f8fSGustavo F. Padovan 	return 0;
38820a708f8fSGustavo F. Padovan }
38830a708f8fSGustavo F. Padovan 
38840a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38850a708f8fSGustavo F. Padovan {
38860a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
38870a708f8fSGustavo F. Padovan 	u16 type;
38880a708f8fSGustavo F. Padovan 
38890a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
38900a708f8fSGustavo F. Padovan 
38910a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
38920a708f8fSGustavo F. Padovan 
38930a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
38940a708f8fSGustavo F. Padovan 		u8 buf[8];
38950a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
38960a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
38970a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
38980a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
38990a708f8fSGustavo F. Padovan 		if (!disable_ertm)
39000a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
39010a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3902a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
39036327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
39046327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3905a5fd6f30SAndrei Emeltchenko 
39060a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
39070a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39080a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
39090a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
39100a708f8fSGustavo F. Padovan 		u8 buf[12];
39110a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
391250a147cdSMat Martineau 
391350a147cdSMat Martineau 		if (enable_hs)
391450a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
391550a147cdSMat Martineau 		else
391650a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
391750a147cdSMat Martineau 
39180a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39190a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3920c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
39210a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39220a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
39230a708f8fSGustavo F. Padovan 	} else {
39240a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
39250a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
39260a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
39270a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39280a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
39290a708f8fSGustavo F. Padovan 	}
39300a708f8fSGustavo F. Padovan 
39310a708f8fSGustavo F. Padovan 	return 0;
39320a708f8fSGustavo F. Padovan }
39330a708f8fSGustavo F. Padovan 
39340a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
39350a708f8fSGustavo F. Padovan {
39360a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
39370a708f8fSGustavo F. Padovan 	u16 type, result;
39380a708f8fSGustavo F. Padovan 
39390a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
39400a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
39410a708f8fSGustavo F. Padovan 
39420a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
39430a708f8fSGustavo F. Padovan 
3944e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3945e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3946e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3947e90165beSAndrei Emeltchenko 		return 0;
3948e90165beSAndrei Emeltchenko 
394917cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
39500a708f8fSGustavo F. Padovan 
39510a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
39520a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39530a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39540a708f8fSGustavo F. Padovan 
39550a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39560a708f8fSGustavo F. Padovan 
39570a708f8fSGustavo F. Padovan 		return 0;
39580a708f8fSGustavo F. Padovan 	}
39590a708f8fSGustavo F. Padovan 
3960978c93b9SAndrei Emeltchenko 	switch (type) {
3961978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
39620a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
39630a708f8fSGustavo F. Padovan 
39640a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
39650a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
39660a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39670a708f8fSGustavo F. Padovan 
39680a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
39690a708f8fSGustavo F. Padovan 
39700a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
39710a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
39720a708f8fSGustavo F. Padovan 		} else {
39730a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39740a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
39750a708f8fSGustavo F. Padovan 
39760a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
39770a708f8fSGustavo F. Padovan 		}
3978978c93b9SAndrei Emeltchenko 		break;
3979978c93b9SAndrei Emeltchenko 
3980978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3981978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
39820a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39830a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39840a708f8fSGustavo F. Padovan 
39850a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3986978c93b9SAndrei Emeltchenko 		break;
39870a708f8fSGustavo F. Padovan 	}
39880a708f8fSGustavo F. Padovan 
39890a708f8fSGustavo F. Padovan 	return 0;
39900a708f8fSGustavo F. Padovan }
39910a708f8fSGustavo F. Padovan 
3992f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3993f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3994f94ff6ffSMat Martineau 					void *data)
3995f94ff6ffSMat Martineau {
3996f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3997f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3998f94ff6ffSMat Martineau 	u16 psm, scid;
3999f94ff6ffSMat Martineau 
4000f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4001f94ff6ffSMat Martineau 		return -EPROTO;
4002f94ff6ffSMat Martineau 
4003f94ff6ffSMat Martineau 	if (!enable_hs)
4004f94ff6ffSMat Martineau 		return -EINVAL;
4005f94ff6ffSMat Martineau 
4006f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4007f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4008f94ff6ffSMat Martineau 
4009f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
4010f94ff6ffSMat Martineau 
4011f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
4012f94ff6ffSMat Martineau 	rsp.dcid = 0;
4013f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
40148ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
40158ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4016f94ff6ffSMat Martineau 
4017f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4018f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4019f94ff6ffSMat Martineau 
4020f94ff6ffSMat Martineau 	return 0;
4021f94ff6ffSMat Martineau }
4022f94ff6ffSMat Martineau 
4023f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
4024f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
4025f94ff6ffSMat Martineau {
4026f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
4027f94ff6ffSMat Martineau 
4028f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
4029f94ff6ffSMat Martineau }
4030f94ff6ffSMat Martineau 
40318d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
40328d5a04a1SMat Martineau 							u16 icid, u16 result)
40338d5a04a1SMat Martineau {
40348d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
40358d5a04a1SMat Martineau 
40368d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40378d5a04a1SMat Martineau 
40388d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40398d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
40408d5a04a1SMat Martineau 
40418d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
40428d5a04a1SMat Martineau }
40438d5a04a1SMat Martineau 
40448d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
40458d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
40468d5a04a1SMat Martineau {
40478d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
40488d5a04a1SMat Martineau 	u8 ident;
40498d5a04a1SMat Martineau 
40508d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40518d5a04a1SMat Martineau 
40528d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
40538d5a04a1SMat Martineau 	if (chan)
40548d5a04a1SMat Martineau 		chan->ident = ident;
40558d5a04a1SMat Martineau 
40568d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
40578d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
40588d5a04a1SMat Martineau 
40598d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
40608d5a04a1SMat Martineau }
40618d5a04a1SMat Martineau 
40628d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
40638d5a04a1SMat Martineau 								u16 icid)
40648d5a04a1SMat Martineau {
40658d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
40668d5a04a1SMat Martineau 
40678d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
40688d5a04a1SMat Martineau 
40698d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40708d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
40718d5a04a1SMat Martineau }
40728d5a04a1SMat Martineau 
40738d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
40748d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40758d5a04a1SMat Martineau {
40768d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
40778d5a04a1SMat Martineau 	u16 icid = 0;
40788d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
40798d5a04a1SMat Martineau 
40808d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
40818d5a04a1SMat Martineau 		return -EPROTO;
40828d5a04a1SMat Martineau 
40838d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
40848d5a04a1SMat Martineau 
40858d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
40868d5a04a1SMat Martineau 
40878d5a04a1SMat Martineau 	if (!enable_hs)
40888d5a04a1SMat Martineau 		return -EINVAL;
40898d5a04a1SMat Martineau 
40908d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
40918d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
40928d5a04a1SMat Martineau 
40938d5a04a1SMat Martineau 	return 0;
40948d5a04a1SMat Martineau }
40958d5a04a1SMat Martineau 
40968d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
40978d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40988d5a04a1SMat Martineau {
40998d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
41008d5a04a1SMat Martineau 	u16 icid, result;
41018d5a04a1SMat Martineau 
41028d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
41038d5a04a1SMat Martineau 		return -EPROTO;
41048d5a04a1SMat Martineau 
41058d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
41068d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
41078d5a04a1SMat Martineau 
41088d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
41098d5a04a1SMat Martineau 
41108d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
41118d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
41128d5a04a1SMat Martineau 
41138d5a04a1SMat Martineau 	return 0;
41148d5a04a1SMat Martineau }
41158d5a04a1SMat Martineau 
41168d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
41178d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
41188d5a04a1SMat Martineau {
41198d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
41208d5a04a1SMat Martineau 	u16 icid, result;
41218d5a04a1SMat Martineau 
41228d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
41238d5a04a1SMat Martineau 		return -EPROTO;
41248d5a04a1SMat Martineau 
41258d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
41268d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
41278d5a04a1SMat Martineau 
41288d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
41298d5a04a1SMat Martineau 
41308d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
41318d5a04a1SMat Martineau 
41328d5a04a1SMat Martineau 	return 0;
41338d5a04a1SMat Martineau }
41348d5a04a1SMat Martineau 
41358d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
41368d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
41378d5a04a1SMat Martineau {
41388d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
41398d5a04a1SMat Martineau 	u16 icid;
41408d5a04a1SMat Martineau 
41418d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
41428d5a04a1SMat Martineau 		return -EPROTO;
41438d5a04a1SMat Martineau 
41448d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
41458d5a04a1SMat Martineau 
41468d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
41478d5a04a1SMat Martineau 
41488d5a04a1SMat Martineau 	return 0;
41498d5a04a1SMat Martineau }
41508d5a04a1SMat Martineau 
4151e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
4152de73115aSClaudio Takahasi 							u16 to_multiplier)
4153de73115aSClaudio Takahasi {
4154de73115aSClaudio Takahasi 	u16 max_latency;
4155de73115aSClaudio Takahasi 
4156de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
4157de73115aSClaudio Takahasi 		return -EINVAL;
4158de73115aSClaudio Takahasi 
4159de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
4160de73115aSClaudio Takahasi 		return -EINVAL;
4161de73115aSClaudio Takahasi 
4162de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
4163de73115aSClaudio Takahasi 		return -EINVAL;
4164de73115aSClaudio Takahasi 
4165de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
4166de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
4167de73115aSClaudio Takahasi 		return -EINVAL;
4168de73115aSClaudio Takahasi 
4169de73115aSClaudio Takahasi 	return 0;
4170de73115aSClaudio Takahasi }
4171de73115aSClaudio Takahasi 
4172de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
4173de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
4174de73115aSClaudio Takahasi {
4175de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
4176de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
4177de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
4178de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
41792ce603ebSClaudio Takahasi 	int err;
4180de73115aSClaudio Takahasi 
4181de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
4182de73115aSClaudio Takahasi 		return -EINVAL;
4183de73115aSClaudio Takahasi 
4184de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
4185de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4186de73115aSClaudio Takahasi 		return -EPROTO;
4187de73115aSClaudio Takahasi 
4188de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4189de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4190de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4191de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4192de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4193de73115aSClaudio Takahasi 
4194de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4195de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
4196de73115aSClaudio Takahasi 
4197de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
41982ce603ebSClaudio Takahasi 
41992ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
42002ce603ebSClaudio Takahasi 	if (err)
4201de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4202de73115aSClaudio Takahasi 	else
4203de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4204de73115aSClaudio Takahasi 
4205de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4206de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
4207de73115aSClaudio Takahasi 
42082ce603ebSClaudio Takahasi 	if (!err)
42092ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
42102ce603ebSClaudio Takahasi 
4211de73115aSClaudio Takahasi 	return 0;
4212de73115aSClaudio Takahasi }
4213de73115aSClaudio Takahasi 
42143300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
42153300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
42163300d9a9SClaudio Takahasi {
42173300d9a9SClaudio Takahasi 	int err = 0;
42183300d9a9SClaudio Takahasi 
42193300d9a9SClaudio Takahasi 	switch (cmd->code) {
42203300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
42213300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
42223300d9a9SClaudio Takahasi 		break;
42233300d9a9SClaudio Takahasi 
42243300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
42253300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
42263300d9a9SClaudio Takahasi 		break;
42273300d9a9SClaudio Takahasi 
42283300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
42293300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
42303300d9a9SClaudio Takahasi 		break;
42313300d9a9SClaudio Takahasi 
42323300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
42333300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
42343300d9a9SClaudio Takahasi 		break;
42353300d9a9SClaudio Takahasi 
42363300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
42373300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
42383300d9a9SClaudio Takahasi 		break;
42393300d9a9SClaudio Takahasi 
42403300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
42413300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
42423300d9a9SClaudio Takahasi 		break;
42433300d9a9SClaudio Takahasi 
42443300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
42453300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
42463300d9a9SClaudio Takahasi 		break;
42473300d9a9SClaudio Takahasi 
42483300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
42493300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
42503300d9a9SClaudio Takahasi 		break;
42513300d9a9SClaudio Takahasi 
42523300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
42533300d9a9SClaudio Takahasi 		break;
42543300d9a9SClaudio Takahasi 
42553300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
42563300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
42573300d9a9SClaudio Takahasi 		break;
42583300d9a9SClaudio Takahasi 
42593300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
42603300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
42613300d9a9SClaudio Takahasi 		break;
42623300d9a9SClaudio Takahasi 
4263f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
4264f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4265f94ff6ffSMat Martineau 		break;
4266f94ff6ffSMat Martineau 
4267f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
4268f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
4269f94ff6ffSMat Martineau 		break;
4270f94ff6ffSMat Martineau 
42718d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
42728d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
42738d5a04a1SMat Martineau 		break;
42748d5a04a1SMat Martineau 
42758d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
42768d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
42778d5a04a1SMat Martineau 		break;
42788d5a04a1SMat Martineau 
42798d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
42808d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
42818d5a04a1SMat Martineau 		break;
42828d5a04a1SMat Martineau 
42838d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
42848d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
42858d5a04a1SMat Martineau 		break;
42868d5a04a1SMat Martineau 
42873300d9a9SClaudio Takahasi 	default:
42883300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
42893300d9a9SClaudio Takahasi 		err = -EINVAL;
42903300d9a9SClaudio Takahasi 		break;
42913300d9a9SClaudio Takahasi 	}
42923300d9a9SClaudio Takahasi 
42933300d9a9SClaudio Takahasi 	return err;
42943300d9a9SClaudio Takahasi }
42953300d9a9SClaudio Takahasi 
42963300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
42973300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
42983300d9a9SClaudio Takahasi {
42993300d9a9SClaudio Takahasi 	switch (cmd->code) {
43003300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
43013300d9a9SClaudio Takahasi 		return 0;
43023300d9a9SClaudio Takahasi 
43033300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
4304de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
43053300d9a9SClaudio Takahasi 
43063300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
43073300d9a9SClaudio Takahasi 		return 0;
43083300d9a9SClaudio Takahasi 
43093300d9a9SClaudio Takahasi 	default:
43103300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
43113300d9a9SClaudio Takahasi 		return -EINVAL;
43123300d9a9SClaudio Takahasi 	}
43133300d9a9SClaudio Takahasi }
43143300d9a9SClaudio Takahasi 
43153300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
43163300d9a9SClaudio Takahasi 							struct sk_buff *skb)
43170a708f8fSGustavo F. Padovan {
43180a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
43190a708f8fSGustavo F. Padovan 	int len = skb->len;
43200a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
43213300d9a9SClaudio Takahasi 	int err;
43220a708f8fSGustavo F. Padovan 
43230a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
43240a708f8fSGustavo F. Padovan 
43250a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
43260a708f8fSGustavo F. Padovan 		u16 cmd_len;
43270a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
43280a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
43290a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
43300a708f8fSGustavo F. Padovan 
43310a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
43320a708f8fSGustavo F. Padovan 
43330a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
43340a708f8fSGustavo F. Padovan 
43350a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
43360a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
43370a708f8fSGustavo F. Padovan 			break;
43380a708f8fSGustavo F. Padovan 		}
43390a708f8fSGustavo F. Padovan 
43403300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
43413300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
43423300d9a9SClaudio Takahasi 		else
43433300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
43440a708f8fSGustavo F. Padovan 
43450a708f8fSGustavo F. Padovan 		if (err) {
4346e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
43472c6d1a2eSGustavo F. Padovan 
43482c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
43490a708f8fSGustavo F. Padovan 
43500a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
4351e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
43520a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
43530a708f8fSGustavo F. Padovan 		}
43540a708f8fSGustavo F. Padovan 
43550a708f8fSGustavo F. Padovan 		data += cmd_len;
43560a708f8fSGustavo F. Padovan 		len  -= cmd_len;
43570a708f8fSGustavo F. Padovan 	}
43580a708f8fSGustavo F. Padovan 
43590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43600a708f8fSGustavo F. Padovan }
43610a708f8fSGustavo F. Padovan 
436247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
43630a708f8fSGustavo F. Padovan {
43640a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
4365e4ca6d98SAndrei Emeltchenko 	int hdr_size;
4366e4ca6d98SAndrei Emeltchenko 
4367e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4368e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
4369e4ca6d98SAndrei Emeltchenko 	else
4370e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
43710a708f8fSGustavo F. Padovan 
437247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
437303a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
43740a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
43750a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
43760a708f8fSGustavo F. Padovan 
43770a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
43780a708f8fSGustavo F. Padovan 			return -EBADMSG;
43790a708f8fSGustavo F. Padovan 	}
43800a708f8fSGustavo F. Padovan 	return 0;
43810a708f8fSGustavo F. Padovan }
43820a708f8fSGustavo F. Padovan 
4383525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
43840a708f8fSGustavo F. Padovan {
4385e31f7633SMat Martineau 	struct l2cap_ctrl control;
43860a708f8fSGustavo F. Padovan 
4387e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
43880a708f8fSGustavo F. Padovan 
4389e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
4390e31f7633SMat Martineau 	control.sframe = 1;
4391e31f7633SMat Martineau 	control.final = 1;
4392e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
4393e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
43940a708f8fSGustavo F. Padovan 
4395e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4396e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
4397e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43980a708f8fSGustavo F. Padovan 	}
43990a708f8fSGustavo F. Padovan 
4400e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4401e31f7633SMat Martineau 	    chan->unacked_frames > 0)
4402e31f7633SMat Martineau 		__set_retrans_timer(chan);
44030a708f8fSGustavo F. Padovan 
4404e31f7633SMat Martineau 	/* Send pending iframes */
4405525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
44060a708f8fSGustavo F. Padovan 
4407e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4408e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4409e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
4410e31f7633SMat Martineau 		 * send it now.
4411e31f7633SMat Martineau 		 */
4412e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
4413e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
44140a708f8fSGustavo F. Padovan 	}
44150a708f8fSGustavo F. Padovan }
44160a708f8fSGustavo F. Padovan 
441784084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
441884084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
44190a708f8fSGustavo F. Padovan {
442084084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
442184084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
442284084a31SMat Martineau 	 */
442384084a31SMat Martineau 	if (!skb_has_frag_list(skb))
442484084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
442584084a31SMat Martineau 
442684084a31SMat Martineau 	new_frag->next = NULL;
442784084a31SMat Martineau 
442884084a31SMat Martineau 	(*last_frag)->next = new_frag;
442984084a31SMat Martineau 	*last_frag = new_frag;
443084084a31SMat Martineau 
443184084a31SMat Martineau 	skb->len += new_frag->len;
443284084a31SMat Martineau 	skb->data_len += new_frag->len;
443384084a31SMat Martineau 	skb->truesize += new_frag->truesize;
443484084a31SMat Martineau }
443584084a31SMat Martineau 
44364b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
44374b51dae9SMat Martineau 				struct l2cap_ctrl *control)
443884084a31SMat Martineau {
443984084a31SMat Martineau 	int err = -EINVAL;
44400a708f8fSGustavo F. Padovan 
44414b51dae9SMat Martineau 	switch (control->sar) {
44427e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
444384084a31SMat Martineau 		if (chan->sdu)
444484084a31SMat Martineau 			break;
44450a708f8fSGustavo F. Padovan 
444684084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
444784084a31SMat Martineau 		break;
44480a708f8fSGustavo F. Padovan 
44497e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
445084084a31SMat Martineau 		if (chan->sdu)
445184084a31SMat Martineau 			break;
44520a708f8fSGustavo F. Padovan 
44536f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
445403a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
44550a708f8fSGustavo F. Padovan 
445684084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
445784084a31SMat Martineau 			err = -EMSGSIZE;
445884084a31SMat Martineau 			break;
445984084a31SMat Martineau 		}
44600a708f8fSGustavo F. Padovan 
446184084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
446284084a31SMat Martineau 			break;
446384084a31SMat Martineau 
446484084a31SMat Martineau 		chan->sdu = skb;
446584084a31SMat Martineau 		chan->sdu_last_frag = skb;
446684084a31SMat Martineau 
446784084a31SMat Martineau 		skb = NULL;
446884084a31SMat Martineau 		err = 0;
44690a708f8fSGustavo F. Padovan 		break;
44700a708f8fSGustavo F. Padovan 
44717e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
44726f61fd47SGustavo F. Padovan 		if (!chan->sdu)
447384084a31SMat Martineau 			break;
44740a708f8fSGustavo F. Padovan 
447584084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
447684084a31SMat Martineau 				&chan->sdu_last_frag);
447784084a31SMat Martineau 		skb = NULL;
44780a708f8fSGustavo F. Padovan 
447984084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
448084084a31SMat Martineau 			break;
44810a708f8fSGustavo F. Padovan 
448284084a31SMat Martineau 		err = 0;
44830a708f8fSGustavo F. Padovan 		break;
44840a708f8fSGustavo F. Padovan 
44857e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
44866f61fd47SGustavo F. Padovan 		if (!chan->sdu)
448784084a31SMat Martineau 			break;
44880a708f8fSGustavo F. Padovan 
448984084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
449084084a31SMat Martineau 				&chan->sdu_last_frag);
449184084a31SMat Martineau 		skb = NULL;
44920a708f8fSGustavo F. Padovan 
449384084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
449484084a31SMat Martineau 			break;
44950a708f8fSGustavo F. Padovan 
449684084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
44970a708f8fSGustavo F. Padovan 
449884084a31SMat Martineau 		if (!err) {
449984084a31SMat Martineau 			/* Reassembly complete */
450084084a31SMat Martineau 			chan->sdu = NULL;
450184084a31SMat Martineau 			chan->sdu_last_frag = NULL;
450284084a31SMat Martineau 			chan->sdu_len = 0;
45030a708f8fSGustavo F. Padovan 		}
45040a708f8fSGustavo F. Padovan 		break;
45050a708f8fSGustavo F. Padovan 	}
45060a708f8fSGustavo F. Padovan 
450784084a31SMat Martineau 	if (err) {
45080a708f8fSGustavo F. Padovan 		kfree_skb(skb);
45096f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
45106f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
451184084a31SMat Martineau 		chan->sdu_last_frag = NULL;
451284084a31SMat Martineau 		chan->sdu_len = 0;
451384084a31SMat Martineau 	}
45140a708f8fSGustavo F. Padovan 
451584084a31SMat Martineau 	return err;
45160a708f8fSGustavo F. Padovan }
45170a708f8fSGustavo F. Padovan 
4518e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
45190a708f8fSGustavo F. Padovan {
452061aa4f5bSMat Martineau 	u8 event;
452161aa4f5bSMat Martineau 
452261aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
452361aa4f5bSMat Martineau 		return;
452461aa4f5bSMat Martineau 
452561aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
452661aa4f5bSMat Martineau 	l2cap_tx(chan, 0, 0, event);
45270a708f8fSGustavo F. Padovan }
45280a708f8fSGustavo F. Padovan 
4529d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
4530d2a7ac5dSMat Martineau {
453163838725SMat Martineau 	int err = 0;
453263838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
453363838725SMat Martineau 	 * until a gap is encountered.
453463838725SMat Martineau 	 */
453563838725SMat Martineau 
453663838725SMat Martineau 	BT_DBG("chan %p", chan);
453763838725SMat Martineau 
453863838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
453963838725SMat Martineau 		struct sk_buff *skb;
454063838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
454163838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
454263838725SMat Martineau 
454363838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
454463838725SMat Martineau 
454563838725SMat Martineau 		if (!skb)
454663838725SMat Martineau 			break;
454763838725SMat Martineau 
454863838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
454963838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
455063838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
455163838725SMat Martineau 		if (err)
455263838725SMat Martineau 			break;
455363838725SMat Martineau 	}
455463838725SMat Martineau 
455563838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
455663838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
455763838725SMat Martineau 		l2cap_send_ack(chan);
455863838725SMat Martineau 	}
455963838725SMat Martineau 
456063838725SMat Martineau 	return err;
4561d2a7ac5dSMat Martineau }
4562d2a7ac5dSMat Martineau 
4563d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
4564d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
4565d2a7ac5dSMat Martineau {
4566f80842a8SMat Martineau 	struct sk_buff *skb;
4567f80842a8SMat Martineau 
4568f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4569f80842a8SMat Martineau 
4570f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4571f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4572f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4573f80842a8SMat Martineau 		return;
4574f80842a8SMat Martineau 	}
4575f80842a8SMat Martineau 
4576f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4577f80842a8SMat Martineau 
4578f80842a8SMat Martineau 	if (skb == NULL) {
4579f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
4580f80842a8SMat Martineau 		       control->reqseq);
4581f80842a8SMat Martineau 		return;
4582f80842a8SMat Martineau 	}
4583f80842a8SMat Martineau 
4584f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
4585f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4586f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4587f80842a8SMat Martineau 		return;
4588f80842a8SMat Martineau 	}
4589f80842a8SMat Martineau 
4590f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4591f80842a8SMat Martineau 
4592f80842a8SMat Martineau 	if (control->poll) {
4593f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
4594f80842a8SMat Martineau 
4595f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4596f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
4597f80842a8SMat Martineau 		l2cap_ertm_send(chan);
4598f80842a8SMat Martineau 
4599f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4600f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
4601f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
4602f80842a8SMat Martineau 		}
4603f80842a8SMat Martineau 	} else {
4604f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
4605f80842a8SMat Martineau 
4606f80842a8SMat Martineau 		if (control->final) {
4607f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
4608f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
4609f80842a8SMat Martineau 						&chan->conn_state))
4610f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
4611f80842a8SMat Martineau 		} else {
4612f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
4613f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4614f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
4615f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
4616f80842a8SMat Martineau 			}
4617f80842a8SMat Martineau 		}
4618f80842a8SMat Martineau 	}
4619d2a7ac5dSMat Martineau }
4620d2a7ac5dSMat Martineau 
4621d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
4622d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
4623d2a7ac5dSMat Martineau {
4624fcd289dfSMat Martineau 	struct sk_buff *skb;
4625fcd289dfSMat Martineau 
4626fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4627fcd289dfSMat Martineau 
4628fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4629fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4630fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4631fcd289dfSMat Martineau 		return;
4632fcd289dfSMat Martineau 	}
4633fcd289dfSMat Martineau 
4634fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4635fcd289dfSMat Martineau 
4636fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
4637fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
4638fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4639fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4640fcd289dfSMat Martineau 		return;
4641fcd289dfSMat Martineau 	}
4642fcd289dfSMat Martineau 
4643fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4644fcd289dfSMat Martineau 
4645fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
4646fcd289dfSMat Martineau 
4647fcd289dfSMat Martineau 	if (control->final) {
4648fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4649fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
4650fcd289dfSMat Martineau 	} else {
4651fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
4652fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
4653fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
4654fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
4655fcd289dfSMat Martineau 	}
4656d2a7ac5dSMat Martineau }
4657d2a7ac5dSMat Martineau 
46584b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
46594b51dae9SMat Martineau {
46604b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
46614b51dae9SMat Martineau 
46624b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
46634b51dae9SMat Martineau 	       chan->expected_tx_seq);
46644b51dae9SMat Martineau 
46654b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
46664b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46674b51dae9SMat Martineau 								chan->tx_win) {
46684b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
46694b51dae9SMat Martineau 			 * invalid packets.
46704b51dae9SMat Martineau 			 */
46714b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
46724b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
46734b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
46744b51dae9SMat Martineau 			} else {
46754b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
46764b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
46774b51dae9SMat Martineau 			}
46784b51dae9SMat Martineau 		}
46794b51dae9SMat Martineau 
46804b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
46814b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
46824b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
46834b51dae9SMat Martineau 		}
46844b51dae9SMat Martineau 
46854b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
46864b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
46874b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
46884b51dae9SMat Martineau 		}
46894b51dae9SMat Martineau 
46904b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
46914b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
46924b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
46934b51dae9SMat Martineau 		}
46944b51dae9SMat Martineau 	}
46954b51dae9SMat Martineau 
46964b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
46974b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46984b51dae9SMat Martineau 		    chan->tx_win) {
46994b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
47004b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
47014b51dae9SMat Martineau 		} else {
47024b51dae9SMat Martineau 			BT_DBG("Expected");
47034b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
47044b51dae9SMat Martineau 		}
47054b51dae9SMat Martineau 	}
47064b51dae9SMat Martineau 
47074b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
47084b51dae9SMat Martineau 		__seq_offset(chan, chan->expected_tx_seq,
47094b51dae9SMat Martineau 			     chan->last_acked_seq)){
47104b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
47114b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
47124b51dae9SMat Martineau 	}
47134b51dae9SMat Martineau 
47144b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
47154b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
47164b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
47174b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
47184b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
47194b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
47204b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
47214b51dae9SMat Martineau 		 * request.
47224b51dae9SMat Martineau 		 *
47234b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
47244b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
47254b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
47264b51dae9SMat Martineau 		 *
47274b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
47284b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
47294b51dae9SMat Martineau 		 * causes a disconnect.
47304b51dae9SMat Martineau 		 */
47314b51dae9SMat Martineau 
47324b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
47334b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
47344b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
47354b51dae9SMat Martineau 		} else {
47364b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
47374b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
47384b51dae9SMat Martineau 		}
47394b51dae9SMat Martineau 	} else {
47404b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
47414b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
47424b51dae9SMat Martineau 	}
47434b51dae9SMat Martineau }
47444b51dae9SMat Martineau 
4745d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
4746d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
4747d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
4748d2a7ac5dSMat Martineau {
4749d2a7ac5dSMat Martineau 	int err = 0;
4750d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4751d2a7ac5dSMat Martineau 
4752d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4753d2a7ac5dSMat Martineau 	       event);
4754d2a7ac5dSMat Martineau 
4755d2a7ac5dSMat Martineau 	switch (event) {
4756d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4757d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
4758d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4759d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4760d2a7ac5dSMat Martineau 
4761d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4762d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
4763d2a7ac5dSMat Martineau 				       control->txseq);
4764d2a7ac5dSMat Martineau 				break;
4765d2a7ac5dSMat Martineau 			}
4766d2a7ac5dSMat Martineau 
4767d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
4768d2a7ac5dSMat Martineau 							   control->txseq);
4769d2a7ac5dSMat Martineau 
4770d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
4771d2a7ac5dSMat Martineau 			skb_in_use = 1;
4772d2a7ac5dSMat Martineau 
4773d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
4774d2a7ac5dSMat Martineau 			if (err)
4775d2a7ac5dSMat Martineau 				break;
4776d2a7ac5dSMat Martineau 
4777d2a7ac5dSMat Martineau 			if (control->final) {
4778d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
4779d2a7ac5dSMat Martineau 							&chan->conn_state)) {
4780d2a7ac5dSMat Martineau 					control->final = 0;
4781d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
4782d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
4783d2a7ac5dSMat Martineau 				}
4784d2a7ac5dSMat Martineau 			}
4785d2a7ac5dSMat Martineau 
4786d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
4787d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
4788d2a7ac5dSMat Martineau 			break;
4789d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4790d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4791d2a7ac5dSMat Martineau 
4792d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
4793d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
4794d2a7ac5dSMat Martineau 			 * when local busy is exited.
4795d2a7ac5dSMat Martineau 			 */
4796d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4797d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
4798d2a7ac5dSMat Martineau 				       control->txseq);
4799d2a7ac5dSMat Martineau 				break;
4800d2a7ac5dSMat Martineau 			}
4801d2a7ac5dSMat Martineau 
4802d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
4803d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
4804d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
4805d2a7ac5dSMat Martineau 			 */
4806d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4807d2a7ac5dSMat Martineau 			skb_in_use = 1;
4808d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4809d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4810d2a7ac5dSMat Martineau 
4811d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
4812d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
4813d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4814d2a7ac5dSMat Martineau 
4815d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
4816d2a7ac5dSMat Martineau 			break;
4817d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4818d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4819d2a7ac5dSMat Martineau 			break;
4820d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4821d2a7ac5dSMat Martineau 			break;
4822d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4823d2a7ac5dSMat Martineau 		default:
4824d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4825d2a7ac5dSMat Martineau 					       ECONNRESET);
4826d2a7ac5dSMat Martineau 			break;
4827d2a7ac5dSMat Martineau 		}
4828d2a7ac5dSMat Martineau 		break;
4829d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4830d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4831d2a7ac5dSMat Martineau 		if (control->final) {
4832d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4833d2a7ac5dSMat Martineau 
4834d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4835d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4836d2a7ac5dSMat Martineau 				control->final = 0;
4837d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4838d2a7ac5dSMat Martineau 			}
4839d2a7ac5dSMat Martineau 
4840d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4841d2a7ac5dSMat Martineau 		} else if (control->poll) {
4842d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
4843d2a7ac5dSMat Martineau 		} else {
4844d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4845d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4846d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4847d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4848d2a7ac5dSMat Martineau 
4849d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4850d2a7ac5dSMat Martineau 		}
4851d2a7ac5dSMat Martineau 		break;
4852d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4853d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4854d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4855d2a7ac5dSMat Martineau 		if (control && control->poll) {
4856d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4857d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
4858d2a7ac5dSMat Martineau 		}
4859d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
4860d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
4861d2a7ac5dSMat Martineau 		break;
4862d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4863d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4864d2a7ac5dSMat Martineau 		break;
4865d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4866d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4867d2a7ac5dSMat Martineau 		break;
4868d2a7ac5dSMat Martineau 	default:
4869d2a7ac5dSMat Martineau 		break;
4870d2a7ac5dSMat Martineau 	}
4871d2a7ac5dSMat Martineau 
4872d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4873d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4874d2a7ac5dSMat Martineau 		kfree_skb(skb);
4875d2a7ac5dSMat Martineau 	}
4876d2a7ac5dSMat Martineau 
4877d2a7ac5dSMat Martineau 	return err;
4878d2a7ac5dSMat Martineau }
4879d2a7ac5dSMat Martineau 
4880d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
4881d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
4882d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
4883d2a7ac5dSMat Martineau {
4884d2a7ac5dSMat Martineau 	int err = 0;
4885d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
4886d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4887d2a7ac5dSMat Martineau 
4888d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4889d2a7ac5dSMat Martineau 	       event);
4890d2a7ac5dSMat Martineau 
4891d2a7ac5dSMat Martineau 	switch (event) {
4892d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4893d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
4894d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4895d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
4896d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4897d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4898d2a7ac5dSMat Martineau 			skb_in_use = 1;
4899d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4900d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4901d2a7ac5dSMat Martineau 
4902d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
4903d2a7ac5dSMat Martineau 			break;
4904d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
4905d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
4906d2a7ac5dSMat Martineau 
4907d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4908d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4909d2a7ac5dSMat Martineau 			skb_in_use = 1;
4910d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4911d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4912d2a7ac5dSMat Martineau 
4913d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
4914d2a7ac5dSMat Martineau 			if (err)
4915d2a7ac5dSMat Martineau 				break;
4916d2a7ac5dSMat Martineau 
4917d2a7ac5dSMat Martineau 			break;
4918d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4919d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
4920d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
4921d2a7ac5dSMat Martineau 			 * the missing frames.
4922d2a7ac5dSMat Martineau 			 */
4923d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4924d2a7ac5dSMat Martineau 			skb_in_use = 1;
4925d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4926d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4927d2a7ac5dSMat Martineau 
4928d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4929d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4930d2a7ac5dSMat Martineau 			break;
4931d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
4932d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
4933d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
4934d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
4935d2a7ac5dSMat Martineau 			 * SREJ'd frames.
4936d2a7ac5dSMat Martineau 			 */
4937d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4938d2a7ac5dSMat Martineau 			skb_in_use = 1;
4939d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4940d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4941d2a7ac5dSMat Martineau 
4942d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4943d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
4944d2a7ac5dSMat Martineau 			break;
4945d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
4946d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
4947d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4948d2a7ac5dSMat Martineau 			break;
4949d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4950d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
4951d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
4952d2a7ac5dSMat Martineau 			 */
4953d2a7ac5dSMat Martineau 			break;
4954d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4955d2a7ac5dSMat Martineau 			break;
4956d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4957d2a7ac5dSMat Martineau 		default:
4958d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4959d2a7ac5dSMat Martineau 					       ECONNRESET);
4960d2a7ac5dSMat Martineau 			break;
4961d2a7ac5dSMat Martineau 		}
4962d2a7ac5dSMat Martineau 		break;
4963d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4964d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4965d2a7ac5dSMat Martineau 		if (control->final) {
4966d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4967d2a7ac5dSMat Martineau 
4968d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4969d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4970d2a7ac5dSMat Martineau 				control->final = 0;
4971d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4972d2a7ac5dSMat Martineau 			}
4973d2a7ac5dSMat Martineau 
4974d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4975d2a7ac5dSMat Martineau 		} else if (control->poll) {
4976d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4977d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4978d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
4979d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4980d2a7ac5dSMat Martineau 			}
4981d2a7ac5dSMat Martineau 
4982d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4983d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4984d2a7ac5dSMat Martineau 		} else {
4985d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4986d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4987d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4988d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4989d2a7ac5dSMat Martineau 
4990d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
4991d2a7ac5dSMat Martineau 		}
4992d2a7ac5dSMat Martineau 		break;
4993d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4994d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4995d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4996d2a7ac5dSMat Martineau 		if (control->poll) {
4997d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4998d2a7ac5dSMat Martineau 		} else {
4999d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
5000d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
5001d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
5002d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
5003d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
5004d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
5005d2a7ac5dSMat Martineau 		}
5006d2a7ac5dSMat Martineau 
5007d2a7ac5dSMat Martineau 		break;
5008d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
5009d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
5010d2a7ac5dSMat Martineau 		break;
5011d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
5012d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
5013d2a7ac5dSMat Martineau 		break;
5014d2a7ac5dSMat Martineau 	}
5015d2a7ac5dSMat Martineau 
5016d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
5017d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
5018d2a7ac5dSMat Martineau 		kfree_skb(skb);
5019d2a7ac5dSMat Martineau 	}
5020d2a7ac5dSMat Martineau 
5021d2a7ac5dSMat Martineau 	return err;
5022d2a7ac5dSMat Martineau }
5023d2a7ac5dSMat Martineau 
5024d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
5025d2a7ac5dSMat Martineau {
5026d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
5027d2a7ac5dSMat Martineau 	u16 unacked;
5028d2a7ac5dSMat Martineau 
5029d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
5030d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
5031d2a7ac5dSMat Martineau }
5032d2a7ac5dSMat Martineau 
5033cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5034cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
50350a708f8fSGustavo F. Padovan {
5036d2a7ac5dSMat Martineau 	int err = 0;
5037d2a7ac5dSMat Martineau 
5038d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
5039d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
5040d2a7ac5dSMat Martineau 
5041d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
5042d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
5043d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
5044d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
5045d2a7ac5dSMat Martineau 			break;
5046d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
5047d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
5048d2a7ac5dSMat Martineau 						       event);
5049d2a7ac5dSMat Martineau 			break;
5050d2a7ac5dSMat Martineau 		default:
5051d2a7ac5dSMat Martineau 			/* shut it down */
5052d2a7ac5dSMat Martineau 			break;
5053d2a7ac5dSMat Martineau 		}
5054d2a7ac5dSMat Martineau 	} else {
5055d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
5056d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
5057d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
5058d2a7ac5dSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
5059d2a7ac5dSMat Martineau 	}
5060d2a7ac5dSMat Martineau 
5061d2a7ac5dSMat Martineau 	return err;
5062cec8ab6eSMat Martineau }
5063cec8ab6eSMat Martineau 
5064cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5065cec8ab6eSMat Martineau 			   struct sk_buff *skb)
5066cec8ab6eSMat Martineau {
50674b51dae9SMat Martineau 	int err = 0;
50684b51dae9SMat Martineau 
50694b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
50704b51dae9SMat Martineau 	       chan->rx_state);
50714b51dae9SMat Martineau 
50724b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
50734b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
50744b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
50754b51dae9SMat Martineau 
50764b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
50774b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
50784b51dae9SMat Martineau 
50794b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
50804b51dae9SMat Martineau 
50814b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
50824b51dae9SMat Martineau 	} else {
50834b51dae9SMat Martineau 		if (chan->sdu) {
50844b51dae9SMat Martineau 			kfree_skb(chan->sdu);
50854b51dae9SMat Martineau 			chan->sdu = NULL;
50864b51dae9SMat Martineau 		}
50874b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
50884b51dae9SMat Martineau 		chan->sdu_len = 0;
50894b51dae9SMat Martineau 
50904b51dae9SMat Martineau 		if (skb) {
50914b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
50924b51dae9SMat Martineau 			kfree_skb(skb);
50934b51dae9SMat Martineau 		}
50944b51dae9SMat Martineau 	}
50954b51dae9SMat Martineau 
50964b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
50974b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
50984b51dae9SMat Martineau 
50994b51dae9SMat Martineau 	return err;
5100cec8ab6eSMat Martineau }
5101cec8ab6eSMat Martineau 
5102cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
5103cec8ab6eSMat Martineau {
5104cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
5105cec8ab6eSMat Martineau 	u16 len;
5106cec8ab6eSMat Martineau 	u8 event;
51070a708f8fSGustavo F. Padovan 
5108b76bbd66SMat Martineau 	__unpack_control(chan, skb);
5109b76bbd66SMat Martineau 
51100a708f8fSGustavo F. Padovan 	len = skb->len;
51110a708f8fSGustavo F. Padovan 
51120a708f8fSGustavo F. Padovan 	/*
51130a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
51140a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
5115cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
51160a708f8fSGustavo F. Padovan 	 */
511747d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
51180a708f8fSGustavo F. Padovan 		goto drop;
51190a708f8fSGustavo F. Padovan 
5120cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
512103a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
51220a708f8fSGustavo F. Padovan 
512347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
512403a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
51250a708f8fSGustavo F. Padovan 
512647d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
51278c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51280a708f8fSGustavo F. Padovan 		goto drop;
51290a708f8fSGustavo F. Padovan 	}
51300a708f8fSGustavo F. Padovan 
5131cec8ab6eSMat Martineau 	if (!control->sframe) {
5132cec8ab6eSMat Martineau 		int err;
51330a708f8fSGustavo F. Padovan 
5134cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
5135cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
5136cec8ab6eSMat Martineau 		       control->txseq);
5137836be934SAndrei Emeltchenko 
5138cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
5139cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
5140cec8ab6eSMat Martineau 		 */
5141cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
51420a708f8fSGustavo F. Padovan 			goto drop;
51430a708f8fSGustavo F. Padovan 
5144cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
5145cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
5146cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
51470a708f8fSGustavo F. Padovan 		} else {
5148cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
5149cec8ab6eSMat Martineau 		}
5150cec8ab6eSMat Martineau 
5151cec8ab6eSMat Martineau 		if (err)
5152cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
5153cec8ab6eSMat Martineau 					       ECONNRESET);
5154cec8ab6eSMat Martineau 	} else {
5155cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
5156cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5157cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5158cec8ab6eSMat Martineau 		};
5159cec8ab6eSMat Martineau 
5160cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
5161cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
5162cec8ab6eSMat Martineau 			goto drop;
5163cec8ab6eSMat Martineau 
5164cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5165cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
5166cec8ab6eSMat Martineau 		       control->super);
5167cec8ab6eSMat Martineau 
51680a708f8fSGustavo F. Padovan 		if (len != 0) {
51690a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
51708c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51710a708f8fSGustavo F. Padovan 			goto drop;
51720a708f8fSGustavo F. Padovan 		}
51730a708f8fSGustavo F. Padovan 
5174cec8ab6eSMat Martineau 		/* Validate F and P bits */
5175cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
5176cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5177cec8ab6eSMat Martineau 			goto drop;
5178cec8ab6eSMat Martineau 
5179cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
5180cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
5181cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51820a708f8fSGustavo F. Padovan 	}
51830a708f8fSGustavo F. Padovan 
51840a708f8fSGustavo F. Padovan 	return 0;
51850a708f8fSGustavo F. Padovan 
51860a708f8fSGustavo F. Padovan drop:
51870a708f8fSGustavo F. Padovan 	kfree_skb(skb);
51880a708f8fSGustavo F. Padovan 	return 0;
51890a708f8fSGustavo F. Padovan }
51900a708f8fSGustavo F. Padovan 
51910a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
51920a708f8fSGustavo F. Padovan {
519348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
51940a708f8fSGustavo F. Padovan 
5195baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
519648454079SGustavo F. Padovan 	if (!chan) {
51970a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
51986be36555SAndrei Emeltchenko 		/* Drop packet and return */
51993379013bSDan Carpenter 		kfree_skb(skb);
52006be36555SAndrei Emeltchenko 		return 0;
52010a708f8fSGustavo F. Padovan 	}
52020a708f8fSGustavo F. Padovan 
520349208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
52040a708f8fSGustavo F. Padovan 
520589bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
52060a708f8fSGustavo F. Padovan 		goto drop;
52070a708f8fSGustavo F. Padovan 
52080c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
52090a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
52100a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
52110a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
52120a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
52130a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
52140a708f8fSGustavo F. Padovan 
52150c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
52160a708f8fSGustavo F. Padovan 			goto drop;
52170a708f8fSGustavo F. Padovan 
521823070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
52190a708f8fSGustavo F. Padovan 			goto done;
52200a708f8fSGustavo F. Padovan 		break;
52210a708f8fSGustavo F. Padovan 
52220a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
52230a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
5224cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
52250a708f8fSGustavo F. Padovan 		goto done;
52260a708f8fSGustavo F. Padovan 
52270a708f8fSGustavo F. Padovan 	default:
52280c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
52290a708f8fSGustavo F. Padovan 		break;
52300a708f8fSGustavo F. Padovan 	}
52310a708f8fSGustavo F. Padovan 
52320a708f8fSGustavo F. Padovan drop:
52330a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52340a708f8fSGustavo F. Padovan 
52350a708f8fSGustavo F. Padovan done:
52366be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
52370a708f8fSGustavo F. Padovan 
52380a708f8fSGustavo F. Padovan 	return 0;
52390a708f8fSGustavo F. Padovan }
52400a708f8fSGustavo F. Padovan 
52410a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
52420a708f8fSGustavo F. Padovan {
524323691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52440a708f8fSGustavo F. Padovan 
5245c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
524623691d75SGustavo F. Padovan 	if (!chan)
52470a708f8fSGustavo F. Padovan 		goto drop;
52480a708f8fSGustavo F. Padovan 
52495b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52500a708f8fSGustavo F. Padovan 
525189bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52520a708f8fSGustavo F. Padovan 		goto drop;
52530a708f8fSGustavo F. Padovan 
5254e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52550a708f8fSGustavo F. Padovan 		goto drop;
52560a708f8fSGustavo F. Padovan 
525723070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
52585b4cedaaSAndrei Emeltchenko 		return 0;
52590a708f8fSGustavo F. Padovan 
52600a708f8fSGustavo F. Padovan drop:
52610a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52620a708f8fSGustavo F. Padovan 
52630a708f8fSGustavo F. Padovan 	return 0;
52640a708f8fSGustavo F. Padovan }
52650a708f8fSGustavo F. Padovan 
5266d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5267d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
52689f69bda6SGustavo F. Padovan {
526923691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52709f69bda6SGustavo F. Padovan 
5271c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
527223691d75SGustavo F. Padovan 	if (!chan)
52739f69bda6SGustavo F. Padovan 		goto drop;
52749f69bda6SGustavo F. Padovan 
52755b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52769f69bda6SGustavo F. Padovan 
527789bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52789f69bda6SGustavo F. Padovan 		goto drop;
52799f69bda6SGustavo F. Padovan 
5280e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52819f69bda6SGustavo F. Padovan 		goto drop;
52829f69bda6SGustavo F. Padovan 
528323070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
52845b4cedaaSAndrei Emeltchenko 		return 0;
52859f69bda6SGustavo F. Padovan 
52869f69bda6SGustavo F. Padovan drop:
52879f69bda6SGustavo F. Padovan 	kfree_skb(skb);
52889f69bda6SGustavo F. Padovan 
52899f69bda6SGustavo F. Padovan 	return 0;
52909f69bda6SGustavo F. Padovan }
52919f69bda6SGustavo F. Padovan 
52920a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
52930a708f8fSGustavo F. Padovan {
52940a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
52950a708f8fSGustavo F. Padovan 	u16 cid, len;
52960a708f8fSGustavo F. Padovan 	__le16 psm;
52970a708f8fSGustavo F. Padovan 
52980a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
52990a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
53000a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
53010a708f8fSGustavo F. Padovan 
53020a708f8fSGustavo F. Padovan 	if (len != skb->len) {
53030a708f8fSGustavo F. Padovan 		kfree_skb(skb);
53040a708f8fSGustavo F. Padovan 		return;
53050a708f8fSGustavo F. Padovan 	}
53060a708f8fSGustavo F. Padovan 
53070a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
53080a708f8fSGustavo F. Padovan 
53090a708f8fSGustavo F. Padovan 	switch (cid) {
53103300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
53110a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
53120a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
53130a708f8fSGustavo F. Padovan 		break;
53140a708f8fSGustavo F. Padovan 
53150a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
5316097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
53170a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
53180a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
53190a708f8fSGustavo F. Padovan 		break;
53200a708f8fSGustavo F. Padovan 
53219f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
53229f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
53239f69bda6SGustavo F. Padovan 		break;
53249f69bda6SGustavo F. Padovan 
5325b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
5326b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
5327b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
5328b501d6a1SAnderson Briglia 		break;
5329b501d6a1SAnderson Briglia 
53300a708f8fSGustavo F. Padovan 	default:
53310a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
53320a708f8fSGustavo F. Padovan 		break;
53330a708f8fSGustavo F. Padovan 	}
53340a708f8fSGustavo F. Padovan }
53350a708f8fSGustavo F. Padovan 
53360a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
53370a708f8fSGustavo F. Padovan 
5338686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
53390a708f8fSGustavo F. Padovan {
53400a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
534123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
53420a708f8fSGustavo F. Padovan 
53430a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
53440a708f8fSGustavo F. Padovan 
53450a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
534623691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
534723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
534823691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
53494343478fSGustavo F. Padovan 
535089bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
53510a708f8fSGustavo F. Padovan 			continue;
53520a708f8fSGustavo F. Padovan 
53530a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
53540a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
535543bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53560a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
53570a708f8fSGustavo F. Padovan 			exact++;
53580a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
53590a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
536043bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53610a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
53620a708f8fSGustavo F. Padovan 		}
53630a708f8fSGustavo F. Padovan 	}
536423691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
53650a708f8fSGustavo F. Padovan 
53660a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
53670a708f8fSGustavo F. Padovan }
53680a708f8fSGustavo F. Padovan 
5369686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
53700a708f8fSGustavo F. Padovan {
53710a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
53720a708f8fSGustavo F. Padovan 
53730a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
53740a708f8fSGustavo F. Padovan 
53750a708f8fSGustavo F. Padovan 	if (!status) {
53760a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
53770a708f8fSGustavo F. Padovan 		if (conn)
53780a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
53790a708f8fSGustavo F. Padovan 	} else
5380e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
53810a708f8fSGustavo F. Padovan 
53820a708f8fSGustavo F. Padovan 	return 0;
53830a708f8fSGustavo F. Padovan }
53840a708f8fSGustavo F. Padovan 
5385686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
53860a708f8fSGustavo F. Padovan {
53870a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
53880a708f8fSGustavo F. Padovan 
53890a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
53900a708f8fSGustavo F. Padovan 
5391686ebf28SUlisses Furquim 	if (!conn)
53929f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
53930a708f8fSGustavo F. Padovan 	return conn->disc_reason;
53940a708f8fSGustavo F. Padovan }
53950a708f8fSGustavo F. Padovan 
5396686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
53970a708f8fSGustavo F. Padovan {
53980a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
53990a708f8fSGustavo F. Padovan 
5400e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
54010a708f8fSGustavo F. Padovan 	return 0;
54020a708f8fSGustavo F. Padovan }
54030a708f8fSGustavo F. Padovan 
54044343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
54050a708f8fSGustavo F. Padovan {
5406715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
54070a708f8fSGustavo F. Padovan 		return;
54080a708f8fSGustavo F. Padovan 
54090a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
54104343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
5411ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
54124343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
54130f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
54140a708f8fSGustavo F. Padovan 	} else {
54154343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
5416c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
54170a708f8fSGustavo F. Padovan 	}
54180a708f8fSGustavo F. Padovan }
54190a708f8fSGustavo F. Padovan 
5420686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
54210a708f8fSGustavo F. Padovan {
54220a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
542348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
54240a708f8fSGustavo F. Padovan 
54250a708f8fSGustavo F. Padovan 	if (!conn)
54260a708f8fSGustavo F. Padovan 		return 0;
54270a708f8fSGustavo F. Padovan 
54280a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
54290a708f8fSGustavo F. Padovan 
5430160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
543135d4adccSHemant Gupta 		if (!status && encrypt)
5432160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
543317cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
5434160dc6acSVinicius Costa Gomes 	}
5435160dc6acSVinicius Costa Gomes 
54363df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
54370a708f8fSGustavo F. Padovan 
54383df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
54396be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
54400a708f8fSGustavo F. Padovan 
5441f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
5442f1cb9af5SVinicius Costa Gomes 
5443f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
5444f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
5445f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
5446cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
5447f1cb9af5SVinicius Costa Gomes 			}
5448f1cb9af5SVinicius Costa Gomes 
54496be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
5450f1cb9af5SVinicius Costa Gomes 			continue;
5451f1cb9af5SVinicius Costa Gomes 		}
5452f1cb9af5SVinicius Costa Gomes 
5453c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
54546be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54550a708f8fSGustavo F. Padovan 			continue;
54560a708f8fSGustavo F. Padovan 		}
54570a708f8fSGustavo F. Padovan 
545889bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
545989bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
5460a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
5461a7d7723aSGustavo Padovan 
5462c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
5463a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
5464a7d7723aSGustavo Padovan 
54654343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
54666be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54670a708f8fSGustavo F. Padovan 			continue;
54680a708f8fSGustavo F. Padovan 		}
54690a708f8fSGustavo F. Padovan 
547089bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
54710a708f8fSGustavo F. Padovan 			if (!status) {
54729b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
54730a708f8fSGustavo F. Padovan 			} else {
5474ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
54750a708f8fSGustavo F. Padovan 			}
547689bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
54776be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
54780a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5479df3c3931SJohan Hedberg 			__u16 res, stat;
54800a708f8fSGustavo F. Padovan 
54816be36555SAndrei Emeltchenko 			lock_sock(sk);
54826be36555SAndrei Emeltchenko 
54830a708f8fSGustavo F. Padovan 			if (!status) {
5484c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
5485c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
5486df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
5487df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
5488df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
548905e9a2f6SIlia Kolomisnky 					if (parent)
5490df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
5491df3c3931SJohan Hedberg 				} else {
54920e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
5493df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
5494df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
5495df3c3931SJohan Hedberg 				}
54960a708f8fSGustavo F. Padovan 			} else {
54970e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
5498ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
5499df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
5500df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
55010a708f8fSGustavo F. Padovan 			}
55020a708f8fSGustavo F. Padovan 
55036be36555SAndrei Emeltchenko 			release_sock(sk);
55046be36555SAndrei Emeltchenko 
5505fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5506fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5507df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
5508df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
5509fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5510fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
55110a708f8fSGustavo F. Padovan 		}
55120a708f8fSGustavo F. Padovan 
55136be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
55140a708f8fSGustavo F. Padovan 	}
55150a708f8fSGustavo F. Padovan 
55163df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
55170a708f8fSGustavo F. Padovan 
55180a708f8fSGustavo F. Padovan 	return 0;
55190a708f8fSGustavo F. Padovan }
55200a708f8fSGustavo F. Padovan 
5521686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
55220a708f8fSGustavo F. Padovan {
55230a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
55240a708f8fSGustavo F. Padovan 
55250a708f8fSGustavo F. Padovan 	if (!conn)
55260a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
55270a708f8fSGustavo F. Padovan 
55280a708f8fSGustavo F. Padovan 	if (!conn)
55290a708f8fSGustavo F. Padovan 		goto drop;
55300a708f8fSGustavo F. Padovan 
55310a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
55320a708f8fSGustavo F. Padovan 
55330a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
55340a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
55350a708f8fSGustavo F. Padovan 		int len;
55360a708f8fSGustavo F. Padovan 
55370a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
55380a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
55390a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55400a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55410a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55420a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55430a708f8fSGustavo F. Padovan 		}
55440a708f8fSGustavo F. Padovan 
55450a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
55460a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
55470a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
55480a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55490a708f8fSGustavo F. Padovan 			goto drop;
55500a708f8fSGustavo F. Padovan 		}
55510a708f8fSGustavo F. Padovan 
55520a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
55530a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
55540a708f8fSGustavo F. Padovan 
55550a708f8fSGustavo F. Padovan 		if (len == skb->len) {
55560a708f8fSGustavo F. Padovan 			/* Complete frame received */
55570a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
55580a708f8fSGustavo F. Padovan 			return 0;
55590a708f8fSGustavo F. Padovan 		}
55600a708f8fSGustavo F. Padovan 
55610a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
55620a708f8fSGustavo F. Padovan 
55630a708f8fSGustavo F. Padovan 		if (skb->len > len) {
55640a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
55650a708f8fSGustavo F. Padovan 				skb->len, len);
55660a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55670a708f8fSGustavo F. Padovan 			goto drop;
55680a708f8fSGustavo F. Padovan 		}
55690a708f8fSGustavo F. Padovan 
55700a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
55710a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
55720a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
55730a708f8fSGustavo F. Padovan 			goto drop;
55740a708f8fSGustavo F. Padovan 
55750a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55760a708f8fSGustavo F. Padovan 								skb->len);
55770a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
55780a708f8fSGustavo F. Padovan 	} else {
55790a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
55800a708f8fSGustavo F. Padovan 
55810a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
55820a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
55830a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55840a708f8fSGustavo F. Padovan 			goto drop;
55850a708f8fSGustavo F. Padovan 		}
55860a708f8fSGustavo F. Padovan 
55870a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
55880a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
55890a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
55900a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55910a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55920a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55930a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55940a708f8fSGustavo F. Padovan 			goto drop;
55950a708f8fSGustavo F. Padovan 		}
55960a708f8fSGustavo F. Padovan 
55970a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55980a708f8fSGustavo F. Padovan 								skb->len);
55990a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
56000a708f8fSGustavo F. Padovan 
56010a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
56020a708f8fSGustavo F. Padovan 			/* Complete frame received */
56030a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
56040a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
56050a708f8fSGustavo F. Padovan 		}
56060a708f8fSGustavo F. Padovan 	}
56070a708f8fSGustavo F. Padovan 
56080a708f8fSGustavo F. Padovan drop:
56090a708f8fSGustavo F. Padovan 	kfree_skb(skb);
56100a708f8fSGustavo F. Padovan 	return 0;
56110a708f8fSGustavo F. Padovan }
56120a708f8fSGustavo F. Padovan 
56130a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
56140a708f8fSGustavo F. Padovan {
561523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
56160a708f8fSGustavo F. Padovan 
5617333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
56180a708f8fSGustavo F. Padovan 
561923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
562023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
56210a708f8fSGustavo F. Padovan 
5622903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
56230a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
56240a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
562589bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
562623691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
562723691d75SGustavo F. Padovan 					c->sec_level, c->mode);
56280a708f8fSGustavo F. Padovan 	}
56290a708f8fSGustavo F. Padovan 
5630333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
56310a708f8fSGustavo F. Padovan 
56320a708f8fSGustavo F. Padovan 	return 0;
56330a708f8fSGustavo F. Padovan }
56340a708f8fSGustavo F. Padovan 
56350a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
56360a708f8fSGustavo F. Padovan {
56370a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
56380a708f8fSGustavo F. Padovan }
56390a708f8fSGustavo F. Padovan 
56400a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
56410a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
56420a708f8fSGustavo F. Padovan 	.read		= seq_read,
56430a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
56440a708f8fSGustavo F. Padovan 	.release	= single_release,
56450a708f8fSGustavo F. Padovan };
56460a708f8fSGustavo F. Padovan 
56470a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
56480a708f8fSGustavo F. Padovan 
564964274518SGustavo F. Padovan int __init l2cap_init(void)
56500a708f8fSGustavo F. Padovan {
56510a708f8fSGustavo F. Padovan 	int err;
56520a708f8fSGustavo F. Padovan 
5653bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
56540a708f8fSGustavo F. Padovan 	if (err < 0)
56550a708f8fSGustavo F. Padovan 		return err;
56560a708f8fSGustavo F. Padovan 
56570a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
56580a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
56590a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
56600a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
56610a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
56620a708f8fSGustavo F. Padovan 	}
56630a708f8fSGustavo F. Padovan 
56640a708f8fSGustavo F. Padovan 	return 0;
56650a708f8fSGustavo F. Padovan }
56660a708f8fSGustavo F. Padovan 
566764274518SGustavo F. Padovan void l2cap_exit(void)
56680a708f8fSGustavo F. Padovan {
56690a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5670bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
56710a708f8fSGustavo F. Padovan }
56720a708f8fSGustavo F. Padovan 
56730a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
56740a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5675