xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision f522ae36)
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 
60eb939922SRusty Russell bool disable_ertm;
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 
760a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7771ba0e56SGustavo F. Padovan 
78baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
790a708f8fSGustavo F. Padovan {
803df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
81baa7e1faSGustavo F. Padovan 
823df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
833df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
843df91ea2SAndrei Emeltchenko 			return c;
850a708f8fSGustavo F. Padovan 	}
863df91ea2SAndrei Emeltchenko 	return NULL;
87baa7e1faSGustavo F. Padovan }
880a708f8fSGustavo F. Padovan 
89baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
900a708f8fSGustavo F. Padovan {
913df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
92baa7e1faSGustavo F. Padovan 
933df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
943df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
953df91ea2SAndrei Emeltchenko 			return c;
960a708f8fSGustavo F. Padovan 	}
973df91ea2SAndrei Emeltchenko 	return NULL;
98baa7e1faSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
1000a708f8fSGustavo F. Padovan /* Find channel with given SCID.
1010a708f8fSGustavo F. Padovan  * Returns locked socket */
102baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1030a708f8fSGustavo F. Padovan {
10448454079SGustavo F. Padovan 	struct l2cap_chan *c;
105baa7e1faSGustavo F. Padovan 
1063df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
107baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
1083df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1093df91ea2SAndrei Emeltchenko 
11048454079SGustavo F. Padovan 	return c;
1110a708f8fSGustavo F. Padovan }
1120a708f8fSGustavo F. Padovan 
113baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1140a708f8fSGustavo F. Padovan {
1153df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
116baa7e1faSGustavo F. Padovan 
1173df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1183df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1193df91ea2SAndrei Emeltchenko 			return c;
1200a708f8fSGustavo F. Padovan 	}
1213df91ea2SAndrei Emeltchenko 	return NULL;
122baa7e1faSGustavo F. Padovan }
1230a708f8fSGustavo F. Padovan 
12423691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1259e4425ffSGustavo F. Padovan {
12623691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1279e4425ffSGustavo F. Padovan 
12823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
12923691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
13023691d75SGustavo F. Padovan 			return c;
1319e4425ffSGustavo F. Padovan 	}
132250938cbSSzymon Janc 	return NULL;
133250938cbSSzymon Janc }
1349e4425ffSGustavo F. Padovan 
1359e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1369e4425ffSGustavo F. Padovan {
13773b2ec18SGustavo F. Padovan 	int err;
13873b2ec18SGustavo F. Padovan 
139333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1409e4425ffSGustavo F. Padovan 
14123691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
14273b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
14373b2ec18SGustavo F. Padovan 		goto done;
1449e4425ffSGustavo F. Padovan 	}
1459e4425ffSGustavo F. Padovan 
14673b2ec18SGustavo F. Padovan 	if (psm) {
1479e4425ffSGustavo F. Padovan 		chan->psm = psm;
1489e4425ffSGustavo F. Padovan 		chan->sport = psm;
14973b2ec18SGustavo F. Padovan 		err = 0;
15073b2ec18SGustavo F. Padovan 	} else {
15173b2ec18SGustavo F. Padovan 		u16 p;
1529e4425ffSGustavo F. Padovan 
15373b2ec18SGustavo F. Padovan 		err = -EINVAL;
15473b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
15523691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
15673b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
15773b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
15873b2ec18SGustavo F. Padovan 				err = 0;
15973b2ec18SGustavo F. Padovan 				break;
16073b2ec18SGustavo F. Padovan 			}
16173b2ec18SGustavo F. Padovan 	}
16273b2ec18SGustavo F. Padovan 
16373b2ec18SGustavo F. Padovan done:
164333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
16573b2ec18SGustavo F. Padovan 	return err;
1669e4425ffSGustavo F. Padovan }
1679e4425ffSGustavo F. Padovan 
1689e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1699e4425ffSGustavo F. Padovan {
170333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1719e4425ffSGustavo F. Padovan 
1729e4425ffSGustavo F. Padovan 	chan->scid = scid;
1739e4425ffSGustavo F. Padovan 
174333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1759e4425ffSGustavo F. Padovan 
1769e4425ffSGustavo F. Padovan 	return 0;
1779e4425ffSGustavo F. Padovan }
1789e4425ffSGustavo F. Padovan 
179baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1800a708f8fSGustavo F. Padovan {
1810a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1820a708f8fSGustavo F. Padovan 
1830a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
184baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1850a708f8fSGustavo F. Padovan 			return cid;
1860a708f8fSGustavo F. Padovan 	}
1870a708f8fSGustavo F. Padovan 
1880a708f8fSGustavo F. Padovan 	return 0;
1890a708f8fSGustavo F. Padovan }
1900a708f8fSGustavo F. Padovan 
1910e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
19289bc500eSGustavo F. Padovan {
19342d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
194badaaa00SGustavo F. Padovan 						state_to_string(state));
195badaaa00SGustavo F. Padovan 
19689bc500eSGustavo F. Padovan 	chan->state = state;
19789bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
19889bc500eSGustavo F. Padovan }
19989bc500eSGustavo F. Padovan 
2000e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2010e587be7SAndrei Emeltchenko {
2020e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2030e587be7SAndrei Emeltchenko 
2040e587be7SAndrei Emeltchenko 	lock_sock(sk);
2050e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2060e587be7SAndrei Emeltchenko 	release_sock(sk);
2070e587be7SAndrei Emeltchenko }
2080e587be7SAndrei Emeltchenko 
2092e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2102e0052e4SAndrei Emeltchenko {
2112e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2122e0052e4SAndrei Emeltchenko 
2132e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2142e0052e4SAndrei Emeltchenko }
2152e0052e4SAndrei Emeltchenko 
2162e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2172e0052e4SAndrei Emeltchenko {
2182e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2192e0052e4SAndrei Emeltchenko 
2202e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2212e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2222e0052e4SAndrei Emeltchenko 	release_sock(sk);
2232e0052e4SAndrei Emeltchenko }
2242e0052e4SAndrei Emeltchenko 
2253c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2263c588192SMat Martineau 
2273c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2283c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2293c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2303c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2313c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2323c588192SMat Martineau  * and removed from the head in constant time, without further memory
2333c588192SMat Martineau  * allocs or frees.
2343c588192SMat Martineau  */
2353c588192SMat Martineau 
2363c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2373c588192SMat Martineau {
2383c588192SMat Martineau 	size_t alloc_size, i;
2393c588192SMat Martineau 
2403c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2413c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2423c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2433c588192SMat Martineau 	 */
2443c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2453c588192SMat Martineau 
2463c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2473c588192SMat Martineau 	if (!seq_list->list)
2483c588192SMat Martineau 		return -ENOMEM;
2493c588192SMat Martineau 
2503c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2513c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2523c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2533c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2543c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2553c588192SMat Martineau 
2563c588192SMat Martineau 	return 0;
2573c588192SMat Martineau }
2583c588192SMat Martineau 
2593c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2603c588192SMat Martineau {
2613c588192SMat Martineau 	kfree(seq_list->list);
2623c588192SMat Martineau }
2633c588192SMat Martineau 
2643c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2653c588192SMat Martineau 					   u16 seq)
2663c588192SMat Martineau {
2673c588192SMat Martineau 	/* Constant-time check for list membership */
2683c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2693c588192SMat Martineau }
2703c588192SMat Martineau 
2713c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2723c588192SMat Martineau {
2733c588192SMat Martineau 	u16 mask = seq_list->mask;
2743c588192SMat Martineau 
2753c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2763c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2773c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2783c588192SMat Martineau 	} else if (seq_list->head == seq) {
2793c588192SMat Martineau 		/* Head can be removed in constant time */
2803c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2813c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2823c588192SMat Martineau 
2833c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
2843c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2853c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2863c588192SMat Martineau 		}
2873c588192SMat Martineau 	} else {
2883c588192SMat Martineau 		/* Walk the list to find the sequence number */
2893c588192SMat Martineau 		u16 prev = seq_list->head;
2903c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
2913c588192SMat Martineau 			prev = seq_list->list[prev & mask];
2923c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
2933c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
2943c588192SMat Martineau 		}
2953c588192SMat Martineau 
2963c588192SMat Martineau 		/* Unlink the number from the list and clear it */
2973c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
2983c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2993c588192SMat Martineau 		if (seq_list->tail == seq)
3003c588192SMat Martineau 			seq_list->tail = prev;
3013c588192SMat Martineau 	}
3023c588192SMat Martineau 	return seq;
3033c588192SMat Martineau }
3043c588192SMat Martineau 
3053c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3063c588192SMat Martineau {
3073c588192SMat Martineau 	/* Remove the head in constant time */
3083c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3093c588192SMat Martineau }
3103c588192SMat Martineau 
3113c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3123c588192SMat Martineau {
3133c588192SMat Martineau 	u16 i;
314*f522ae36SGustavo Padovan 
315*f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
316*f522ae36SGustavo Padovan 		return;
317*f522ae36SGustavo Padovan 
3183c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3193c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3203c588192SMat Martineau 
3213c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3223c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3233c588192SMat Martineau }
3243c588192SMat Martineau 
3253c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3263c588192SMat Martineau {
3273c588192SMat Martineau 	u16 mask = seq_list->mask;
3283c588192SMat Martineau 
3293c588192SMat Martineau 	/* All appends happen in constant time */
3303c588192SMat Martineau 
331*f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
332*f522ae36SGustavo Padovan 		return;
333*f522ae36SGustavo Padovan 
3343c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3353c588192SMat Martineau 		seq_list->head = seq;
3363c588192SMat Martineau 	else
3373c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3383c588192SMat Martineau 
3393c588192SMat Martineau 	seq_list->tail = seq;
3403c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3413c588192SMat Martineau }
3423c588192SMat Martineau 
343721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
344ab07801dSGustavo F. Padovan {
345721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
346721c4181SGustavo F. Padovan 							chan_timer.work);
3473df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
348ab07801dSGustavo F. Padovan 	int reason;
349ab07801dSGustavo F. Padovan 
350e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
351ab07801dSGustavo F. Padovan 
3523df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3536be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
354ab07801dSGustavo F. Padovan 
35589bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
356ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
35789bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
358ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
359ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
360ab07801dSGustavo F. Padovan 	else
361ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
362ab07801dSGustavo F. Padovan 
3630f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
364ab07801dSGustavo F. Padovan 
3656be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
366ab07801dSGustavo F. Padovan 
367ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3683df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3693df91ea2SAndrei Emeltchenko 
370371fd835SUlisses Furquim 	l2cap_chan_put(chan);
371ab07801dSGustavo F. Padovan }
372ab07801dSGustavo F. Padovan 
373eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3740a708f8fSGustavo F. Padovan {
37548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3760a708f8fSGustavo F. Padovan 
37748454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
37848454079SGustavo F. Padovan 	if (!chan)
37948454079SGustavo F. Padovan 		return NULL;
3800a708f8fSGustavo F. Padovan 
381c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
382c03b355eSAndrei Emeltchenko 
383333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
38423691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
385333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
38623691d75SGustavo F. Padovan 
387721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
388ab07801dSGustavo F. Padovan 
38989bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
39089bc500eSGustavo F. Padovan 
39171ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
39271ba0e56SGustavo F. Padovan 
393eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
394abc545b8SSzymon Janc 
39548454079SGustavo F. Padovan 	return chan;
3960a708f8fSGustavo F. Padovan }
3970a708f8fSGustavo F. Padovan 
39823691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
3996ff5abbfSGustavo F. Padovan {
400333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40123691d75SGustavo F. Padovan 	list_del(&chan->global_l);
402333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40323691d75SGustavo F. Padovan 
404371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4056ff5abbfSGustavo F. Padovan }
4066ff5abbfSGustavo F. Padovan 
407bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
408bd4b1653SAndrei Emeltchenko {
409bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
410bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
411bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
412bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
413bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
414bd4b1653SAndrei Emeltchenko 
415bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
416bd4b1653SAndrei Emeltchenko }
417bd4b1653SAndrei Emeltchenko 
41814a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4190a708f8fSGustavo F. Padovan {
4200a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
421097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4220a708f8fSGustavo F. Padovan 
4239f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4240a708f8fSGustavo F. Padovan 
4258c1d787bSGustavo F. Padovan 	chan->conn = conn;
4260a708f8fSGustavo F. Padovan 
4275491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4285491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
429b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
430b62f328bSVille Tervo 			/* LE connection */
4310c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
432fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
433fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
434b62f328bSVille Tervo 		} else {
4350a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
436fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4370c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
438b62f328bSVille Tervo 		}
4395491120eSAndrei Emeltchenko 		break;
4405491120eSAndrei Emeltchenko 
4415491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4420a708f8fSGustavo F. Padovan 		/* Connectionless socket */
443fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
444fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4450c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4465491120eSAndrei Emeltchenko 		break;
4475491120eSAndrei Emeltchenko 
4485491120eSAndrei Emeltchenko 	default:
4490a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
450fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
451fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4520c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4530a708f8fSGustavo F. Padovan 	}
4540a708f8fSGustavo F. Padovan 
4558f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4568f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4578f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4588f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4598f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4608f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4618f7975b1SAndrei Emeltchenko 
462371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
463baa7e1faSGustavo F. Padovan 
4643df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
465643162a8SAndrei Emeltchenko }
466643162a8SAndrei Emeltchenko 
46714a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
468643162a8SAndrei Emeltchenko {
469643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
470643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4720a708f8fSGustavo F. Padovan }
4730a708f8fSGustavo F. Padovan 
4744519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4750a708f8fSGustavo F. Padovan {
47648454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4778c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4780a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
4790a708f8fSGustavo F. Padovan 
480c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
4810a708f8fSGustavo F. Padovan 
48249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
4830a708f8fSGustavo F. Padovan 
4840a708f8fSGustavo F. Padovan 	if (conn) {
485baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
4863df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
4873d57dc68SGustavo F. Padovan 
488371fd835SUlisses Furquim 		l2cap_chan_put(chan);
489baa7e1faSGustavo F. Padovan 
4908c1d787bSGustavo F. Padovan 		chan->conn = NULL;
4910a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
4920a708f8fSGustavo F. Padovan 	}
4930a708f8fSGustavo F. Padovan 
4946be36555SAndrei Emeltchenko 	lock_sock(sk);
4956be36555SAndrei Emeltchenko 
4960e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
4970a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
4980a708f8fSGustavo F. Padovan 
4990a708f8fSGustavo F. Padovan 	if (err)
5002e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5010a708f8fSGustavo F. Padovan 
5020a708f8fSGustavo F. Padovan 	if (parent) {
5030a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5040a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5050a708f8fSGustavo F. Padovan 	} else
5060a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5070a708f8fSGustavo F. Padovan 
5086be36555SAndrei Emeltchenko 	release_sock(sk);
5096be36555SAndrei Emeltchenko 
510c1360a1cSGustavo F. Padovan 	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
511c1360a1cSGustavo F. Padovan 			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
5126ff5abbfSGustavo F. Padovan 		return;
5132ead70b8SGustavo F. Padovan 
51458d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5150a708f8fSGustavo F. Padovan 
5160c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5170a708f8fSGustavo F. Padovan 		struct srej_list *l, *tmp;
5180a708f8fSGustavo F. Padovan 
5191a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5201a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5211a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5220a708f8fSGustavo F. Padovan 
523f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5240a708f8fSGustavo F. Padovan 
5253c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5263c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
52739d5a3eeSGustavo F. Padovan 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
5280a708f8fSGustavo F. Padovan 			list_del(&l->list);
5290a708f8fSGustavo F. Padovan 			kfree(l);
5300a708f8fSGustavo F. Padovan 		}
5310a708f8fSGustavo F. Padovan 	}
5320a708f8fSGustavo F. Padovan }
5330a708f8fSGustavo F. Padovan 
5344519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5354519de9aSGustavo F. Padovan {
5364519de9aSGustavo F. Padovan 	struct sock *sk;
5374519de9aSGustavo F. Padovan 
5384519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5394519de9aSGustavo F. Padovan 
5404519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5410f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
542ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5433df91ea2SAndrei Emeltchenko 
5446be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
545c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
546ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5476be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5483df91ea2SAndrei Emeltchenko 
549ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5500f852724SGustavo F. Padovan 	}
5514519de9aSGustavo F. Padovan }
5524519de9aSGustavo F. Padovan 
5530f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5544519de9aSGustavo F. Padovan {
5554519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5564519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5574519de9aSGustavo F. Padovan 
558e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
559e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5604519de9aSGustavo F. Padovan 
56189bc500eSGustavo F. Padovan 	switch (chan->state) {
5624519de9aSGustavo F. Padovan 	case BT_LISTEN:
5636be36555SAndrei Emeltchenko 		lock_sock(sk);
5644519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
56589bc500eSGustavo F. Padovan 
5660e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
56789bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5686be36555SAndrei Emeltchenko 		release_sock(sk);
5694519de9aSGustavo F. Padovan 		break;
5704519de9aSGustavo F. Padovan 
5714519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5724519de9aSGustavo F. Padovan 	case BT_CONFIG:
573715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5744519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
575c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5764519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5774519de9aSGustavo F. Padovan 		} else
5784519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5794519de9aSGustavo F. Padovan 		break;
5804519de9aSGustavo F. Padovan 
5814519de9aSGustavo F. Padovan 	case BT_CONNECT2:
582715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5834519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5844519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5854519de9aSGustavo F. Padovan 			__u16 result;
5864519de9aSGustavo F. Padovan 
5874519de9aSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup)
5884519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
5894519de9aSGustavo F. Padovan 			else
5904519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
59189bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
5924519de9aSGustavo F. Padovan 
5934519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5944519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5954519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
5964519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
5974519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5984519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
5994519de9aSGustavo F. Padovan 		}
6004519de9aSGustavo F. Padovan 
6014519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6024519de9aSGustavo F. Padovan 		break;
6034519de9aSGustavo F. Padovan 
6044519de9aSGustavo F. Padovan 	case BT_CONNECT:
6054519de9aSGustavo F. Padovan 	case BT_DISCONN:
6064519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6074519de9aSGustavo F. Padovan 		break;
6084519de9aSGustavo F. Padovan 
6094519de9aSGustavo F. Padovan 	default:
6106be36555SAndrei Emeltchenko 		lock_sock(sk);
6114519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6126be36555SAndrei Emeltchenko 		release_sock(sk);
6134519de9aSGustavo F. Padovan 		break;
6144519de9aSGustavo F. Padovan 	}
6154519de9aSGustavo F. Padovan }
6164519de9aSGustavo F. Padovan 
6174343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6180a708f8fSGustavo F. Padovan {
619715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6204343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6210a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6220a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6230a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6240a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6250a708f8fSGustavo F. Padovan 		default:
6260a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6270a708f8fSGustavo F. Padovan 		}
628fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6294343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6304343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6310a708f8fSGustavo F. Padovan 
6324343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6330a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6340a708f8fSGustavo F. Padovan 		else
6350a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6360a708f8fSGustavo F. Padovan 	} else {
6374343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6380a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6390a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6400a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6410a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6420a708f8fSGustavo F. Padovan 		default:
6430a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6440a708f8fSGustavo F. Padovan 		}
6450a708f8fSGustavo F. Padovan 	}
6460a708f8fSGustavo F. Padovan }
6470a708f8fSGustavo F. Padovan 
6480a708f8fSGustavo F. Padovan /* Service level security */
649d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6500a708f8fSGustavo F. Padovan {
6518c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6520a708f8fSGustavo F. Padovan 	__u8 auth_type;
6530a708f8fSGustavo F. Padovan 
6544343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6550a708f8fSGustavo F. Padovan 
6564343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6570a708f8fSGustavo F. Padovan }
6580a708f8fSGustavo F. Padovan 
659b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6600a708f8fSGustavo F. Padovan {
6610a708f8fSGustavo F. Padovan 	u8 id;
6620a708f8fSGustavo F. Padovan 
6630a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6640a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6650a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6660a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6670a708f8fSGustavo F. Padovan 	 */
6680a708f8fSGustavo F. Padovan 
669333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6700a708f8fSGustavo F. Padovan 
6710a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6720a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6730a708f8fSGustavo F. Padovan 
6740a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6750a708f8fSGustavo F. Padovan 
676333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6770a708f8fSGustavo F. Padovan 
6780a708f8fSGustavo F. Padovan 	return id;
6790a708f8fSGustavo F. Padovan }
6800a708f8fSGustavo F. Padovan 
6814519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6820a708f8fSGustavo F. Padovan {
6830a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6840a708f8fSGustavo F. Padovan 	u8 flags;
6850a708f8fSGustavo F. Padovan 
6860a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
6870a708f8fSGustavo F. Padovan 
6880a708f8fSGustavo F. Padovan 	if (!skb)
6890a708f8fSGustavo F. Padovan 		return;
6900a708f8fSGustavo F. Padovan 
6910a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
6920a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
6930a708f8fSGustavo F. Padovan 	else
6940a708f8fSGustavo F. Padovan 		flags = ACL_START;
6950a708f8fSGustavo F. Padovan 
69614b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
6975e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
69814b12d0bSJaikumar Ganesh 
69973d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7000a708f8fSGustavo F. Padovan }
7010a708f8fSGustavo F. Padovan 
70273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
70373d80debSLuiz Augusto von Dentz {
70473d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
70573d80debSLuiz Augusto von Dentz 	u16 flags;
70673d80debSLuiz Augusto von Dentz 
70773d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
70873d80debSLuiz Augusto von Dentz 							skb->priority);
70973d80debSLuiz Augusto von Dentz 
71073d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
71173d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
71273d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
71373d80debSLuiz Augusto von Dentz 	else
71473d80debSLuiz Augusto von Dentz 		flags = ACL_START;
71573d80debSLuiz Augusto von Dentz 
71673d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
71773d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7180a708f8fSGustavo F. Padovan }
7190a708f8fSGustavo F. Padovan 
720b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
721b5c6aaedSMat Martineau {
722b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
723b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
724b5c6aaedSMat Martineau 
725b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
726b5c6aaedSMat Martineau 		/* S-Frame */
727b5c6aaedSMat Martineau 		control->sframe = 1;
728b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
729b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
730b5c6aaedSMat Martineau 
731b5c6aaedSMat Martineau 		control->sar = 0;
732b5c6aaedSMat Martineau 		control->txseq = 0;
733b5c6aaedSMat Martineau 	} else {
734b5c6aaedSMat Martineau 		/* I-Frame */
735b5c6aaedSMat Martineau 		control->sframe = 0;
736b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
737b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
738b5c6aaedSMat Martineau 
739b5c6aaedSMat Martineau 		control->poll = 0;
740b5c6aaedSMat Martineau 		control->super = 0;
741b5c6aaedSMat Martineau 	}
742b5c6aaedSMat Martineau }
743b5c6aaedSMat Martineau 
744b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
745b5c6aaedSMat Martineau {
746b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
747b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
748b5c6aaedSMat Martineau 
749b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
750b5c6aaedSMat Martineau 		/* S-Frame */
751b5c6aaedSMat Martineau 		control->sframe = 1;
752b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
753b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
754b5c6aaedSMat Martineau 
755b5c6aaedSMat Martineau 		control->sar = 0;
756b5c6aaedSMat Martineau 		control->txseq = 0;
757b5c6aaedSMat Martineau 	} else {
758b5c6aaedSMat Martineau 		/* I-Frame */
759b5c6aaedSMat Martineau 		control->sframe = 0;
760b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
761b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
762b5c6aaedSMat Martineau 
763b5c6aaedSMat Martineau 		control->poll = 0;
764b5c6aaedSMat Martineau 		control->super = 0;
765b5c6aaedSMat Martineau 	}
766b5c6aaedSMat Martineau }
767b5c6aaedSMat Martineau 
768b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
769b5c6aaedSMat Martineau 				    struct sk_buff *skb)
770b5c6aaedSMat Martineau {
771b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
772b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
773b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
774b5c6aaedSMat Martineau 	} else {
775b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
776b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
777b5c6aaedSMat Martineau 	}
778b5c6aaedSMat Martineau }
779b5c6aaedSMat Martineau 
780b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
781b5c6aaedSMat Martineau {
782b5c6aaedSMat Martineau 	u32 packed;
783b5c6aaedSMat Martineau 
784b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
785b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
786b5c6aaedSMat Martineau 
787b5c6aaedSMat Martineau 	if (control->sframe) {
788b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
789b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
790b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
791b5c6aaedSMat Martineau 	} else {
792b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
793b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
794b5c6aaedSMat Martineau 	}
795b5c6aaedSMat Martineau 
796b5c6aaedSMat Martineau 	return packed;
797b5c6aaedSMat Martineau }
798b5c6aaedSMat Martineau 
799b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
800b5c6aaedSMat Martineau {
801b5c6aaedSMat Martineau 	u16 packed;
802b5c6aaedSMat Martineau 
803b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
804b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
805b5c6aaedSMat Martineau 
806b5c6aaedSMat Martineau 	if (control->sframe) {
807b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
808b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
809b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
810b5c6aaedSMat Martineau 	} else {
811b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
812b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
813b5c6aaedSMat Martineau 	}
814b5c6aaedSMat Martineau 
815b5c6aaedSMat Martineau 	return packed;
816b5c6aaedSMat Martineau }
817b5c6aaedSMat Martineau 
818b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
819b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
820b5c6aaedSMat Martineau 				  struct sk_buff *skb)
821b5c6aaedSMat Martineau {
822b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
823b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
824b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
825b5c6aaedSMat Martineau 	} else {
826b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
827b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
828b5c6aaedSMat Martineau 	}
829b5c6aaedSMat Martineau }
830b5c6aaedSMat Martineau 
83188843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
8320a708f8fSGustavo F. Padovan {
8330a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8340a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
8358c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
836e4ca6d98SAndrei Emeltchenko 	int count, hlen;
8370a708f8fSGustavo F. Padovan 
83889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
8390a708f8fSGustavo F. Padovan 		return;
8400a708f8fSGustavo F. Padovan 
841e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
842e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
843e4ca6d98SAndrei Emeltchenko 	else
844e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8450a708f8fSGustavo F. Padovan 
8460a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
84703a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8480a708f8fSGustavo F. Padovan 
84988843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
8500a708f8fSGustavo F. Padovan 
8510a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, hlen);
852793c2f1cSAndrei Emeltchenko 
853793c2f1cSAndrei Emeltchenko 	control |= __set_sframe(chan);
8540a708f8fSGustavo F. Padovan 
855e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
85603f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
8570a708f8fSGustavo F. Padovan 
858e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
859e3781735SAndrei Emeltchenko 		control |= __set_ctrl_poll(chan);
8600a708f8fSGustavo F. Padovan 
8610a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
8620a708f8fSGustavo F. Padovan 	if (!skb)
8630a708f8fSGustavo F. Padovan 		return;
8640a708f8fSGustavo F. Padovan 
8650a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8660a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
867fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
86888843ab0SAndrei Emeltchenko 
86988843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
8700a708f8fSGustavo F. Padovan 
87147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
87203a51213SAndrei Emeltchenko 		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
87303a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8740a708f8fSGustavo F. Padovan 	}
8750a708f8fSGustavo F. Padovan 
87673d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
87773d80debSLuiz Augusto von Dentz 	l2cap_do_send(chan, skb);
8780a708f8fSGustavo F. Padovan }
8790a708f8fSGustavo F. Padovan 
88088843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
8810a708f8fSGustavo F. Padovan {
882e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
883ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
884e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
8850a708f8fSGustavo F. Padovan 	} else
886ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
8870a708f8fSGustavo F. Padovan 
8880b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
8890a708f8fSGustavo F. Padovan 
890525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
8910a708f8fSGustavo F. Padovan }
8920a708f8fSGustavo F. Padovan 
893b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
8940a708f8fSGustavo F. Padovan {
895c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
8960a708f8fSGustavo F. Padovan }
8970a708f8fSGustavo F. Padovan 
8989b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
8999b27f350SAndrei Emeltchenko {
9009b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9019b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9029b27f350SAndrei Emeltchenko 
9039b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9049b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9059b27f350SAndrei Emeltchenko 
9069b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9079b27f350SAndrei Emeltchenko 
9089b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9099b27f350SAndrei Emeltchenko 
9109b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9119b27f350SAndrei Emeltchenko }
9129b27f350SAndrei Emeltchenko 
9139f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9149f0caeb1SVinicius Costa Gomes {
9159f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9169f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9179f0caeb1SVinicius Costa Gomes 
9189f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9199f0caeb1SVinicius Costa Gomes 
9209f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9219f0caeb1SVinicius Costa Gomes 
9229f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9239f0caeb1SVinicius Costa Gomes 
9249f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9259f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9269f0caeb1SVinicius Costa Gomes 
9279f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9289f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9299f0caeb1SVinicius Costa Gomes 
9309f0caeb1SVinicius Costa Gomes 	if (parent)
9319f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9329f0caeb1SVinicius Costa Gomes 
9339f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9349f0caeb1SVinicius Costa Gomes }
9359f0caeb1SVinicius Costa Gomes 
936fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9370a708f8fSGustavo F. Padovan {
9388c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9390a708f8fSGustavo F. Padovan 
9409f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9419f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9429f0caeb1SVinicius Costa Gomes 		return;
9439f0caeb1SVinicius Costa Gomes 	}
9449f0caeb1SVinicius Costa Gomes 
9450a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9460a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9470a708f8fSGustavo F. Padovan 			return;
9480a708f8fSGustavo F. Padovan 
949d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9509b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9519b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9520a708f8fSGustavo F. Padovan 	} else {
9530a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9540a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9550a708f8fSGustavo F. Padovan 
9560a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9570a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
9580a708f8fSGustavo F. Padovan 
959ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
9600a708f8fSGustavo F. Padovan 
9610a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
9620a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
9630a708f8fSGustavo F. Padovan 	}
9640a708f8fSGustavo F. Padovan }
9650a708f8fSGustavo F. Padovan 
9660a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
9670a708f8fSGustavo F. Padovan {
9680a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
9690a708f8fSGustavo F. Padovan 	if (!disable_ertm)
9700a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
9710a708f8fSGustavo F. Padovan 
9720a708f8fSGustavo F. Padovan 	switch (mode) {
9730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
9740a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
9750a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
9760a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
9770a708f8fSGustavo F. Padovan 	default:
9780a708f8fSGustavo F. Padovan 		return 0x00;
9790a708f8fSGustavo F. Padovan 	}
9800a708f8fSGustavo F. Padovan }
9810a708f8fSGustavo F. Padovan 
9824519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
9830a708f8fSGustavo F. Padovan {
9846be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
9850a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
9860a708f8fSGustavo F. Padovan 
9870a708f8fSGustavo F. Padovan 	if (!conn)
9880a708f8fSGustavo F. Padovan 		return;
9890a708f8fSGustavo F. Padovan 
9900c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
9911a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
9921a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
9931a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
9940a708f8fSGustavo F. Padovan 	}
9950a708f8fSGustavo F. Padovan 
996fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
997fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
9980a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
9990a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10000a708f8fSGustavo F. Padovan 
10016be36555SAndrei Emeltchenko 	lock_sock(sk);
10020e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10032e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10046be36555SAndrei Emeltchenko 	release_sock(sk);
10050a708f8fSGustavo F. Padovan }
10060a708f8fSGustavo F. Padovan 
10070a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10080a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10090a708f8fSGustavo F. Padovan {
10103df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10110a708f8fSGustavo F. Padovan 
10120a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10130a708f8fSGustavo F. Padovan 
10143df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10150a708f8fSGustavo F. Padovan 
10163df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
101748454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1018baa7e1faSGustavo F. Padovan 
10196be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10200a708f8fSGustavo F. Padovan 
1021715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10226be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10230a708f8fSGustavo F. Padovan 			continue;
10240a708f8fSGustavo F. Padovan 		}
10250a708f8fSGustavo F. Padovan 
102689bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1027d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1028b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10296be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10300a708f8fSGustavo F. Padovan 				continue;
10310a708f8fSGustavo F. Padovan 			}
10320a708f8fSGustavo F. Padovan 
1033c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1034c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1035c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10360f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10376be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10380a708f8fSGustavo F. Padovan 				continue;
10390a708f8fSGustavo F. Padovan 			}
10400a708f8fSGustavo F. Padovan 
10419b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10420a708f8fSGustavo F. Padovan 
104389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10440a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10450a708f8fSGustavo F. Padovan 			char buf[128];
1046fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1047fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10480a708f8fSGustavo F. Padovan 
1049d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10506be36555SAndrei Emeltchenko 				lock_sock(sk);
10510a708f8fSGustavo F. Padovan 				if (bt_sk(sk)->defer_setup) {
10520a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10530a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10540a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
105505e9a2f6SIlia Kolomisnky 					if (parent)
10560a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
10570a708f8fSGustavo F. Padovan 
10580a708f8fSGustavo F. Padovan 				} else {
10590e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
10600a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
10610a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
10620a708f8fSGustavo F. Padovan 				}
10636be36555SAndrei Emeltchenko 				release_sock(sk);
10640a708f8fSGustavo F. Padovan 			} else {
10650a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10660a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
10670a708f8fSGustavo F. Padovan 			}
10680a708f8fSGustavo F. Padovan 
1069fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1070fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
10710a708f8fSGustavo F. Padovan 
1072c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
10730a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
10746be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10750a708f8fSGustavo F. Padovan 				continue;
10760a708f8fSGustavo F. Padovan 			}
10770a708f8fSGustavo F. Padovan 
1078c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
10790a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
108073ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
108173ffa904SGustavo F. Padovan 			chan->num_conf_req++;
10820a708f8fSGustavo F. Padovan 		}
10830a708f8fSGustavo F. Padovan 
10846be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
10850a708f8fSGustavo F. Padovan 	}
10860a708f8fSGustavo F. Padovan 
10873df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
10880a708f8fSGustavo F. Padovan }
10890a708f8fSGustavo F. Padovan 
1090c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1091b62f328bSVille Tervo  * Returns closest match, locked.
1092b62f328bSVille Tervo  */
1093d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1094c2287681SIdo Yariv 						    bdaddr_t *src,
1095c2287681SIdo Yariv 						    bdaddr_t *dst)
1096b62f328bSVille Tervo {
109723691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1098b62f328bSVille Tervo 
109923691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1100b62f328bSVille Tervo 
110123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
110223691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1103fe4128e0SGustavo F. Padovan 
110489bc500eSGustavo F. Padovan 		if (state && c->state != state)
1105b62f328bSVille Tervo 			continue;
1106b62f328bSVille Tervo 
110723691d75SGustavo F. Padovan 		if (c->scid == cid) {
1108c2287681SIdo Yariv 			int src_match, dst_match;
1109c2287681SIdo Yariv 			int src_any, dst_any;
1110c2287681SIdo Yariv 
1111b62f328bSVille Tervo 			/* Exact match. */
1112c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1113c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1114c2287681SIdo Yariv 			if (src_match && dst_match) {
111523691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
111623691d75SGustavo F. Padovan 				return c;
111723691d75SGustavo F. Padovan 			}
1118b62f328bSVille Tervo 
1119b62f328bSVille Tervo 			/* Closest match */
1120c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1121c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1122c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1123c2287681SIdo Yariv 			    (src_any && dst_any))
112423691d75SGustavo F. Padovan 				c1 = c;
1125b62f328bSVille Tervo 		}
1126b62f328bSVille Tervo 	}
1127280f294fSGustavo F. Padovan 
112823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1129b62f328bSVille Tervo 
113023691d75SGustavo F. Padovan 	return c1;
1131b62f328bSVille Tervo }
1132b62f328bSVille Tervo 
1133b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1134b62f328bSVille Tervo {
1135c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
113623691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1137b62f328bSVille Tervo 
1138b62f328bSVille Tervo 	BT_DBG("");
1139b62f328bSVille Tervo 
1140b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
114123691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1142c2287681SIdo Yariv 					  conn->src, conn->dst);
114323691d75SGustavo F. Padovan 	if (!pchan)
1144b62f328bSVille Tervo 		return;
1145b62f328bSVille Tervo 
114623691d75SGustavo F. Padovan 	parent = pchan->sk;
114723691d75SGustavo F. Padovan 
1148aa2ac881SGustavo F. Padovan 	lock_sock(parent);
114962f3a2cfSGustavo F. Padovan 
1150b62f328bSVille Tervo 	/* Check for backlog size */
1151b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1152b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1153b62f328bSVille Tervo 		goto clean;
1154b62f328bSVille Tervo 	}
1155b62f328bSVille Tervo 
115680808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
115780808e43SGustavo F. Padovan 	if (!chan)
1158b62f328bSVille Tervo 		goto clean;
1159b62f328bSVille Tervo 
116080808e43SGustavo F. Padovan 	sk = chan->sk;
11615d41ce1dSGustavo F. Padovan 
1162b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1163b62f328bSVille Tervo 
1164b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1165b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1166b62f328bSVille Tervo 
1167d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1168d1010240SGustavo F. Padovan 
11693d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
117048454079SGustavo F. Padovan 
1171c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1172b62f328bSVille Tervo 
11730e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1174b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1175b62f328bSVille Tervo 
1176b62f328bSVille Tervo clean:
1177aa2ac881SGustavo F. Padovan 	release_sock(parent);
1178b62f328bSVille Tervo }
1179b62f328bSVille Tervo 
11800a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
11810a708f8fSGustavo F. Padovan {
118248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
11830a708f8fSGustavo F. Padovan 
11840a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
11850a708f8fSGustavo F. Padovan 
1186b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1187b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1188b62f328bSVille Tervo 
1189160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1190160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1191160dc6acSVinicius Costa Gomes 
11923df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
11930a708f8fSGustavo F. Padovan 
11943df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1195baa7e1faSGustavo F. Padovan 
11966be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
11970a708f8fSGustavo F. Padovan 
119863128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1199b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1200cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1201acd7d370SVille Tervo 
120263128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12036be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1204c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12056be36555SAndrei Emeltchenko 			lock_sock(sk);
12060e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12070a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12086be36555SAndrei Emeltchenko 			release_sock(sk);
1209b501d6a1SAnderson Briglia 
121089bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1211fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12120a708f8fSGustavo F. Padovan 
12136be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12140a708f8fSGustavo F. Padovan 	}
12150a708f8fSGustavo F. Padovan 
12163df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12170a708f8fSGustavo F. Padovan }
12180a708f8fSGustavo F. Padovan 
12190a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12200a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12210a708f8fSGustavo F. Padovan {
122248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12230a708f8fSGustavo F. Padovan 
12240a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12250a708f8fSGustavo F. Padovan 
12263df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12270a708f8fSGustavo F. Padovan 
12283df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1229ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12302e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12310a708f8fSGustavo F. Padovan 	}
12320a708f8fSGustavo F. Padovan 
12333df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12340a708f8fSGustavo F. Padovan }
12350a708f8fSGustavo F. Padovan 
1236f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12370a708f8fSGustavo F. Padovan {
1238f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1239030013d8SGustavo F. Padovan 							info_timer.work);
12400a708f8fSGustavo F. Padovan 
12410a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12420a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12430a708f8fSGustavo F. Padovan 
12440a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12450a708f8fSGustavo F. Padovan }
12460a708f8fSGustavo F. Padovan 
12475d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12485d3de7dfSVinicius Costa Gomes {
12495d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12505d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12515d3de7dfSVinicius Costa Gomes 
12525d3de7dfSVinicius Costa Gomes 	if (!conn)
12535d3de7dfSVinicius Costa Gomes 		return;
12545d3de7dfSVinicius Costa Gomes 
12555d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12565d3de7dfSVinicius Costa Gomes 
12575d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
12585d3de7dfSVinicius Costa Gomes 
12593df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12603df91ea2SAndrei Emeltchenko 
12615d3de7dfSVinicius Costa Gomes 	/* Kill channels */
12625d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
126361d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
12646be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12656be36555SAndrei Emeltchenko 
12665d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
12676be36555SAndrei Emeltchenko 
12686be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12696be36555SAndrei Emeltchenko 
12705d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
127161d6ef3eSMat Martineau 		l2cap_chan_put(chan);
12725d3de7dfSVinicius Costa Gomes 	}
12735d3de7dfSVinicius Costa Gomes 
12743df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12753df91ea2SAndrei Emeltchenko 
127673d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
127773d80debSLuiz Augusto von Dentz 
12785d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1279127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
12805d3de7dfSVinicius Costa Gomes 
128151a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1282127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
12838aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1284d26a2345SVinicius Costa Gomes 	}
12855d3de7dfSVinicius Costa Gomes 
12865d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
12875d3de7dfSVinicius Costa Gomes 	kfree(conn);
12885d3de7dfSVinicius Costa Gomes }
12895d3de7dfSVinicius Costa Gomes 
12906c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
12915d3de7dfSVinicius Costa Gomes {
12926c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
12936c9d42a1SGustavo F. Padovan 						security_timer.work);
12945d3de7dfSVinicius Costa Gomes 
12955d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
12965d3de7dfSVinicius Costa Gomes }
12975d3de7dfSVinicius Costa Gomes 
12980a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
12990a708f8fSGustavo F. Padovan {
13000a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
130173d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13020a708f8fSGustavo F. Padovan 
13030a708f8fSGustavo F. Padovan 	if (conn || status)
13040a708f8fSGustavo F. Padovan 		return conn;
13050a708f8fSGustavo F. Padovan 
130673d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
130773d80debSLuiz Augusto von Dentz 	if (!hchan)
13080a708f8fSGustavo F. Padovan 		return NULL;
13090a708f8fSGustavo F. Padovan 
131073d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
131173d80debSLuiz Augusto von Dentz 	if (!conn) {
131273d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
131373d80debSLuiz Augusto von Dentz 		return NULL;
131473d80debSLuiz Augusto von Dentz 	}
131573d80debSLuiz Augusto von Dentz 
13160a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13170a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
131873d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13190a708f8fSGustavo F. Padovan 
132073d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13210a708f8fSGustavo F. Padovan 
1322acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1323acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1324acd7d370SVille Tervo 	else
13250a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1326acd7d370SVille Tervo 
13270a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13280a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13290a708f8fSGustavo F. Padovan 
13300a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13310a708f8fSGustavo F. Padovan 
13320a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13333df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1334baa7e1faSGustavo F. Padovan 
1335baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13360a708f8fSGustavo F. Padovan 
13375d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13386c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13395d3de7dfSVinicius Costa Gomes 	else
1340030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13410a708f8fSGustavo F. Padovan 
13429f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13430a708f8fSGustavo F. Padovan 
13440a708f8fSGustavo F. Padovan 	return conn;
13450a708f8fSGustavo F. Padovan }
13460a708f8fSGustavo F. Padovan 
13470a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13480a708f8fSGustavo F. Padovan 
1349c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13500a708f8fSGustavo F. Padovan  * Returns closest match.
13510a708f8fSGustavo F. Padovan  */
1352c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1353c2287681SIdo Yariv 						   bdaddr_t *src,
1354c2287681SIdo Yariv 						   bdaddr_t *dst)
13550a708f8fSGustavo F. Padovan {
135623691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
13570a708f8fSGustavo F. Padovan 
135823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
13590a708f8fSGustavo F. Padovan 
136023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
136123691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1362fe4128e0SGustavo F. Padovan 
136389bc500eSGustavo F. Padovan 		if (state && c->state != state)
13640a708f8fSGustavo F. Padovan 			continue;
13650a708f8fSGustavo F. Padovan 
136623691d75SGustavo F. Padovan 		if (c->psm == psm) {
1367c2287681SIdo Yariv 			int src_match, dst_match;
1368c2287681SIdo Yariv 			int src_any, dst_any;
1369c2287681SIdo Yariv 
13700a708f8fSGustavo F. Padovan 			/* Exact match. */
1371c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1372c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1373c2287681SIdo Yariv 			if (src_match && dst_match) {
1374a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
137523691d75SGustavo F. Padovan 				return c;
137623691d75SGustavo F. Padovan 			}
13770a708f8fSGustavo F. Padovan 
13780a708f8fSGustavo F. Padovan 			/* Closest match */
1379c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1380c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1381c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1382c2287681SIdo Yariv 			    (src_any && dst_any))
138323691d75SGustavo F. Padovan 				c1 = c;
13840a708f8fSGustavo F. Padovan 		}
13850a708f8fSGustavo F. Padovan 	}
13860a708f8fSGustavo F. Padovan 
138723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
13880a708f8fSGustavo F. Padovan 
138923691d75SGustavo F. Padovan 	return c1;
13900a708f8fSGustavo F. Padovan }
13910a708f8fSGustavo F. Padovan 
13928e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
13938e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
13940a708f8fSGustavo F. Padovan {
13955d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
13960a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
13970a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
13980a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
13990a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14000a708f8fSGustavo F. Padovan 	__u8 auth_type;
14010a708f8fSGustavo F. Padovan 	int err;
14020a708f8fSGustavo F. Padovan 
14038e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14048e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14050a708f8fSGustavo F. Padovan 
14060a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14070a708f8fSGustavo F. Padovan 	if (!hdev)
14080a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14090a708f8fSGustavo F. Padovan 
141009fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14110a708f8fSGustavo F. Padovan 
14126be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
141303a00194SGustavo F. Padovan 
141403a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
141503a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
141603a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
141703a00194SGustavo F. Padovan 		err = -EINVAL;
141803a00194SGustavo F. Padovan 		goto done;
141903a00194SGustavo F. Padovan 	}
142003a00194SGustavo F. Padovan 
142103a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
142203a00194SGustavo F. Padovan 		err = -EINVAL;
142303a00194SGustavo F. Padovan 		goto done;
142403a00194SGustavo F. Padovan 	}
142503a00194SGustavo F. Padovan 
142603a00194SGustavo F. Padovan 	switch (chan->mode) {
142703a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
142803a00194SGustavo F. Padovan 		break;
142903a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
143003a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
143103a00194SGustavo F. Padovan 		if (!disable_ertm)
143203a00194SGustavo F. Padovan 			break;
143303a00194SGustavo F. Padovan 		/* fall through */
143403a00194SGustavo F. Padovan 	default:
143503a00194SGustavo F. Padovan 		err = -ENOTSUPP;
143603a00194SGustavo F. Padovan 		goto done;
143703a00194SGustavo F. Padovan 	}
143803a00194SGustavo F. Padovan 
14396be36555SAndrei Emeltchenko 	lock_sock(sk);
14406be36555SAndrei Emeltchenko 
144103a00194SGustavo F. Padovan 	switch (sk->sk_state) {
144203a00194SGustavo F. Padovan 	case BT_CONNECT:
144303a00194SGustavo F. Padovan 	case BT_CONNECT2:
144403a00194SGustavo F. Padovan 	case BT_CONFIG:
144503a00194SGustavo F. Padovan 		/* Already connecting */
144603a00194SGustavo F. Padovan 		err = 0;
14476be36555SAndrei Emeltchenko 		release_sock(sk);
144803a00194SGustavo F. Padovan 		goto done;
144903a00194SGustavo F. Padovan 
145003a00194SGustavo F. Padovan 	case BT_CONNECTED:
145103a00194SGustavo F. Padovan 		/* Already connected */
145203a00194SGustavo F. Padovan 		err = -EISCONN;
14536be36555SAndrei Emeltchenko 		release_sock(sk);
145403a00194SGustavo F. Padovan 		goto done;
145503a00194SGustavo F. Padovan 
145603a00194SGustavo F. Padovan 	case BT_OPEN:
145703a00194SGustavo F. Padovan 	case BT_BOUND:
145803a00194SGustavo F. Padovan 		/* Can connect */
145903a00194SGustavo F. Padovan 		break;
146003a00194SGustavo F. Padovan 
146103a00194SGustavo F. Padovan 	default:
146203a00194SGustavo F. Padovan 		err = -EBADFD;
14636be36555SAndrei Emeltchenko 		release_sock(sk);
146403a00194SGustavo F. Padovan 		goto done;
146503a00194SGustavo F. Padovan 	}
146603a00194SGustavo F. Padovan 
146703a00194SGustavo F. Padovan 	/* Set destination address and psm */
14689219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
14696be36555SAndrei Emeltchenko 
14706be36555SAndrei Emeltchenko 	release_sock(sk);
14716be36555SAndrei Emeltchenko 
147203a00194SGustavo F. Padovan 	chan->psm = psm;
147303a00194SGustavo F. Padovan 	chan->dcid = cid;
14740a708f8fSGustavo F. Padovan 
14754343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
14760a708f8fSGustavo F. Padovan 
1477fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
14788e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
14794343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1480acd7d370SVille Tervo 	else
14818e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
14824343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1483acd7d370SVille Tervo 
148430e76272SVille Tervo 	if (IS_ERR(hcon)) {
148530e76272SVille Tervo 		err = PTR_ERR(hcon);
14860a708f8fSGustavo F. Padovan 		goto done;
148730e76272SVille Tervo 	}
14880a708f8fSGustavo F. Padovan 
14890a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
14900a708f8fSGustavo F. Padovan 	if (!conn) {
14910a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
149230e76272SVille Tervo 		err = -ENOMEM;
14930a708f8fSGustavo F. Padovan 		goto done;
14940a708f8fSGustavo F. Padovan 	}
14950a708f8fSGustavo F. Padovan 
14969f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
14979f0caeb1SVinicius Costa Gomes 		err = 0;
14989f0caeb1SVinicius Costa Gomes 
14999f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15009f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15019f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15029f0caeb1SVinicius Costa Gomes 		}
15039f0caeb1SVinicius Costa Gomes 
15049f0caeb1SVinicius Costa Gomes 		if (err)
15059f0caeb1SVinicius Costa Gomes 			goto done;
15069f0caeb1SVinicius Costa Gomes 	}
15079f0caeb1SVinicius Costa Gomes 
15080a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15090a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15100a708f8fSGustavo F. Padovan 
15116be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
151248454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15136be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
151448454079SGustavo F. Padovan 
15156be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1516c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15170a708f8fSGustavo F. Padovan 
15180a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1519715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1520c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1521d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15226be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15230a708f8fSGustavo F. Padovan 		} else
1524fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15250a708f8fSGustavo F. Padovan 	}
15260a708f8fSGustavo F. Padovan 
152730e76272SVille Tervo 	err = 0;
152830e76272SVille Tervo 
15290a708f8fSGustavo F. Padovan done:
15306be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
153109fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15320a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15330a708f8fSGustavo F. Padovan 	return err;
15340a708f8fSGustavo F. Padovan }
15350a708f8fSGustavo F. Padovan 
1536dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15370a708f8fSGustavo F. Padovan {
15388c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15390a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15400a708f8fSGustavo F. Padovan 	int err = 0;
15410a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15420a708f8fSGustavo F. Padovan 
15430a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15440a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1545a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15460a708f8fSGustavo F. Padovan 		if (!timeo)
15470a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15480a708f8fSGustavo F. Padovan 
15490a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15500a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15510a708f8fSGustavo F. Padovan 			break;
15520a708f8fSGustavo F. Padovan 		}
15530a708f8fSGustavo F. Padovan 
15540a708f8fSGustavo F. Padovan 		release_sock(sk);
15550a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15560a708f8fSGustavo F. Padovan 		lock_sock(sk);
1557a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
15580a708f8fSGustavo F. Padovan 
15590a708f8fSGustavo F. Padovan 		err = sock_error(sk);
15600a708f8fSGustavo F. Padovan 		if (err)
15610a708f8fSGustavo F. Padovan 			break;
15620a708f8fSGustavo F. Padovan 	}
15630a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
15640a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
15650a708f8fSGustavo F. Padovan 	return err;
15660a708f8fSGustavo F. Padovan }
15670a708f8fSGustavo F. Padovan 
1568721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
15690a708f8fSGustavo F. Padovan {
1570721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1571721c4181SGustavo F. Padovan 							monitor_timer.work);
15720a708f8fSGustavo F. Padovan 
1573525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
15740a708f8fSGustavo F. Padovan 
15756be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15766be36555SAndrei Emeltchenko 
15772c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
15788c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
15796be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15808d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
15810a708f8fSGustavo F. Padovan 		return;
15820a708f8fSGustavo F. Padovan 	}
15830a708f8fSGustavo F. Padovan 
15846a026610SGustavo F. Padovan 	chan->retry_count++;
15851a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15860a708f8fSGustavo F. Padovan 
1587525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
15886be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
15898d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
15900a708f8fSGustavo F. Padovan }
15910a708f8fSGustavo F. Padovan 
1592721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
15930a708f8fSGustavo F. Padovan {
1594721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1595721c4181SGustavo F. Padovan 							retrans_timer.work);
15960a708f8fSGustavo F. Padovan 
159749208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
15980a708f8fSGustavo F. Padovan 
15996be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16006be36555SAndrei Emeltchenko 
16016a026610SGustavo F. Padovan 	chan->retry_count = 1;
16021a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
16030a708f8fSGustavo F. Padovan 
1604e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16050a708f8fSGustavo F. Padovan 
1606525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16076be36555SAndrei Emeltchenko 
16086be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16098d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16100a708f8fSGustavo F. Padovan }
16110a708f8fSGustavo F. Padovan 
161242e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
16130a708f8fSGustavo F. Padovan {
16140a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16150a708f8fSGustavo F. Padovan 
161658d35f87SGustavo F. Padovan 	while ((skb = skb_peek(&chan->tx_q)) &&
16176a026610SGustavo F. Padovan 			chan->unacked_frames) {
16183ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
16190a708f8fSGustavo F. Padovan 			break;
16200a708f8fSGustavo F. Padovan 
162158d35f87SGustavo F. Padovan 		skb = skb_dequeue(&chan->tx_q);
16220a708f8fSGustavo F. Padovan 		kfree_skb(skb);
16230a708f8fSGustavo F. Padovan 
16246a026610SGustavo F. Padovan 		chan->unacked_frames--;
16250a708f8fSGustavo F. Padovan 	}
16260a708f8fSGustavo F. Padovan 
16276a026610SGustavo F. Padovan 	if (!chan->unacked_frames)
16281a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
16290a708f8fSGustavo F. Padovan }
16300a708f8fSGustavo F. Padovan 
163167c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan)
16320a708f8fSGustavo F. Padovan {
16330a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
163488843ab0SAndrei Emeltchenko 	u32 control;
163588843ab0SAndrei Emeltchenko 	u16 fcs;
16360a708f8fSGustavo F. Padovan 
163758d35f87SGustavo F. Padovan 	while ((skb = skb_dequeue(&chan->tx_q))) {
163888843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
1639fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
164094122bbeSMat Martineau 		control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
164188843ab0SAndrei Emeltchenko 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
16420a708f8fSGustavo F. Padovan 
164347d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
164403a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
164503a51213SAndrei Emeltchenko 						skb->len - L2CAP_FCS_SIZE);
164603a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs,
164703a51213SAndrei Emeltchenko 					skb->data + skb->len - L2CAP_FCS_SIZE);
16480a708f8fSGustavo F. Padovan 		}
16490a708f8fSGustavo F. Padovan 
16504343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16510a708f8fSGustavo F. Padovan 
1652836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16530a708f8fSGustavo F. Padovan 	}
16540a708f8fSGustavo F. Padovan }
16550a708f8fSGustavo F. Padovan 
1656fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
16570a708f8fSGustavo F. Padovan {
16580a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
165988843ab0SAndrei Emeltchenko 	u16 fcs;
166088843ab0SAndrei Emeltchenko 	u32 control;
16610a708f8fSGustavo F. Padovan 
166258d35f87SGustavo F. Padovan 	skb = skb_peek(&chan->tx_q);
16630a708f8fSGustavo F. Padovan 	if (!skb)
16640a708f8fSGustavo F. Padovan 		return;
16650a708f8fSGustavo F. Padovan 
16663ce3514fSMat Martineau 	while (bt_cb(skb)->control.txseq != tx_seq) {
166758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
16680a708f8fSGustavo F. Padovan 			return;
16690a708f8fSGustavo F. Padovan 
1670d1726b6dSSzymon Janc 		skb = skb_queue_next(&chan->tx_q, skb);
1671d1726b6dSSzymon Janc 	}
16720a708f8fSGustavo F. Padovan 
16733ce3514fSMat Martineau 	if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
16743ce3514fSMat Martineau 	    chan->remote_max_tx) {
16758c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16760a708f8fSGustavo F. Padovan 		return;
16770a708f8fSGustavo F. Padovan 	}
16780a708f8fSGustavo F. Padovan 
16790a708f8fSGustavo F. Padovan 	tx_skb = skb_clone(skb, GFP_ATOMIC);
16803ce3514fSMat Martineau 	bt_cb(skb)->control.retries++;
168188843ab0SAndrei Emeltchenko 
168288843ab0SAndrei Emeltchenko 	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
16837e0ef6eeSAndrei Emeltchenko 	control &= __get_sar_mask(chan);
16840a708f8fSGustavo F. Padovan 
1685e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
168603f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
16870a708f8fSGustavo F. Padovan 
16880b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
1689fb45de7dSAndrei Emeltchenko 	control |= __set_txseq(chan, tx_seq);
16900a708f8fSGustavo F. Padovan 
169188843ab0SAndrei Emeltchenko 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
16920a708f8fSGustavo F. Padovan 
169347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
169403a51213SAndrei Emeltchenko 		fcs = crc16(0, (u8 *)tx_skb->data,
169503a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
169603a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs,
169703a51213SAndrei Emeltchenko 				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
16980a708f8fSGustavo F. Padovan 	}
16990a708f8fSGustavo F. Padovan 
17004343478fSGustavo F. Padovan 	l2cap_do_send(chan, tx_skb);
17010a708f8fSGustavo F. Padovan }
17020a708f8fSGustavo F. Padovan 
170367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
17040a708f8fSGustavo F. Padovan {
17050a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
170688843ab0SAndrei Emeltchenko 	u16 fcs;
170788843ab0SAndrei Emeltchenko 	u32 control;
17080a708f8fSGustavo F. Padovan 	int nsent = 0;
17090a708f8fSGustavo F. Padovan 
171089bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17110a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17120a708f8fSGustavo F. Padovan 
171394122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
171494122bbeSMat Martineau 		return 0;
171594122bbeSMat Martineau 
171658d35f87SGustavo F. Padovan 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
17170a708f8fSGustavo F. Padovan 
17183ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
17193ce3514fSMat Martineau 		    chan->remote_max_tx) {
17208c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
17210a708f8fSGustavo F. Padovan 			break;
17220a708f8fSGustavo F. Padovan 		}
17230a708f8fSGustavo F. Padovan 
17240a708f8fSGustavo F. Padovan 		tx_skb = skb_clone(skb, GFP_ATOMIC);
17250a708f8fSGustavo F. Padovan 
17263ce3514fSMat Martineau 		bt_cb(skb)->control.retries++;
17270a708f8fSGustavo F. Padovan 
172888843ab0SAndrei Emeltchenko 		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
17297e0ef6eeSAndrei Emeltchenko 		control &= __get_sar_mask(chan);
17300a708f8fSGustavo F. Padovan 
1731e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
173203f6715dSAndrei Emeltchenko 			control |= __set_ctrl_final(chan);
1733e2ab4353SGustavo F. Padovan 
17340b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->buffer_seq);
1735fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
173694122bbeSMat Martineau 		control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
17370a708f8fSGustavo F. Padovan 
173888843ab0SAndrei Emeltchenko 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
17390a708f8fSGustavo F. Padovan 
174047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
174103a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
174203a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
174303a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs, skb->data +
174403a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
17450a708f8fSGustavo F. Padovan 		}
17460a708f8fSGustavo F. Padovan 
17474343478fSGustavo F. Padovan 		l2cap_do_send(chan, tx_skb);
17480a708f8fSGustavo F. Padovan 
17491a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17500a708f8fSGustavo F. Padovan 
17513ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = chan->next_tx_seq;
1752836be934SAndrei Emeltchenko 
1753836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17540a708f8fSGustavo F. Padovan 
17553ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == 1) {
17566a026610SGustavo F. Padovan 			chan->unacked_frames++;
1757930fa4aeSSzymon Janc 
1758930fa4aeSSzymon Janc 			if (!nsent++)
1759930fa4aeSSzymon Janc 				__clear_ack_timer(chan);
17608ed7a0aeSSzymon Janc 		}
176123e9fde2SSuraj Sumangala 
17626a026610SGustavo F. Padovan 		chan->frames_sent++;
17630a708f8fSGustavo F. Padovan 
176458d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
176558d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17660a708f8fSGustavo F. Padovan 		else
176758d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
17680a708f8fSGustavo F. Padovan 	}
17690a708f8fSGustavo F. Padovan 
17700a708f8fSGustavo F. Padovan 	return nsent;
17710a708f8fSGustavo F. Padovan }
17720a708f8fSGustavo F. Padovan 
1773525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
17740a708f8fSGustavo F. Padovan {
17750a708f8fSGustavo F. Padovan 	int ret;
17760a708f8fSGustavo F. Padovan 
177758d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
177858d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
17790a708f8fSGustavo F. Padovan 
178042e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1781525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
17820a708f8fSGustavo F. Padovan 	return ret;
17830a708f8fSGustavo F. Padovan }
17840a708f8fSGustavo F. Padovan 
1785b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan)
17860a708f8fSGustavo F. Padovan {
178788843ab0SAndrei Emeltchenko 	u32 control = 0;
17880a708f8fSGustavo F. Padovan 
17890b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
17900a708f8fSGustavo F. Padovan 
1791e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1792ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1793e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1794525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
17950a708f8fSGustavo F. Padovan 		return;
17960a708f8fSGustavo F. Padovan 	}
17970a708f8fSGustavo F. Padovan 
1798525cd185SGustavo F. Padovan 	if (l2cap_ertm_send(chan) > 0)
17990a708f8fSGustavo F. Padovan 		return;
18000a708f8fSGustavo F. Padovan 
1801ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1802525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
18030a708f8fSGustavo F. Padovan }
18040a708f8fSGustavo F. Padovan 
1805b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1806b17e73bbSSzymon Janc {
1807b17e73bbSSzymon Janc 	__clear_ack_timer(chan);
1808b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
1809b17e73bbSSzymon Janc }
1810b17e73bbSSzymon Janc 
1811525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan)
18120a708f8fSGustavo F. Padovan {
18130a708f8fSGustavo F. Padovan 	struct srej_list *tail;
181488843ab0SAndrei Emeltchenko 	u32 control;
18150a708f8fSGustavo F. Padovan 
1816ab784b73SAndrei Emeltchenko 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
181703f6715dSAndrei Emeltchenko 	control |= __set_ctrl_final(chan);
18180a708f8fSGustavo F. Padovan 
181939d5a3eeSGustavo F. Padovan 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
18200b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, tail->tx_seq);
18210a708f8fSGustavo F. Padovan 
1822525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
18230a708f8fSGustavo F. Padovan }
18240a708f8fSGustavo F. Padovan 
182504124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
182604124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
182704124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
18280a708f8fSGustavo F. Padovan {
18290952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
18300a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
183190338947SGustavo Padovan 	int sent = 0;
18320a708f8fSGustavo F. Padovan 
18330a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
18340a708f8fSGustavo F. Padovan 		return -EFAULT;
18350a708f8fSGustavo F. Padovan 
18360a708f8fSGustavo F. Padovan 	sent += count;
18370a708f8fSGustavo F. Padovan 	len  -= count;
18380a708f8fSGustavo F. Padovan 
18390a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
18400a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
18410a708f8fSGustavo F. Padovan 	while (len) {
1842fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1843fbe00700SGustavo Padovan 
18440a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
18450a708f8fSGustavo F. Padovan 
1846fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
184790338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1848fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1849fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
18502f7719ceSAndrei Emeltchenko 
1851fbe00700SGustavo Padovan 		*frag = tmp;
1852fbe00700SGustavo Padovan 
18530a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
18540a708f8fSGustavo F. Padovan 			return -EFAULT;
18550a708f8fSGustavo F. Padovan 
18565e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
18575e59b791SLuiz Augusto von Dentz 
18580a708f8fSGustavo F. Padovan 		sent += count;
18590a708f8fSGustavo F. Padovan 		len  -= count;
18600a708f8fSGustavo F. Padovan 
18612d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
18622d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
18632d0ed3d5SGustavo Padovan 
18640a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
18650a708f8fSGustavo F. Padovan 	}
18660a708f8fSGustavo F. Padovan 
18670a708f8fSGustavo F. Padovan 	return sent;
18680a708f8fSGustavo F. Padovan }
18690a708f8fSGustavo F. Padovan 
18705e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
18715e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18725e59b791SLuiz Augusto von Dentz 						u32 priority)
18730a708f8fSGustavo F. Padovan {
18748c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18750a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
187603a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
18770a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18780a708f8fSGustavo F. Padovan 
18796d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
18800a708f8fSGustavo F. Padovan 
18810a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18822f7719ceSAndrei Emeltchenko 
18832f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
188490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
188590338947SGustavo Padovan 	if (IS_ERR(skb))
188690338947SGustavo Padovan 		return skb;
18870a708f8fSGustavo F. Padovan 
18885e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18895e59b791SLuiz Augusto von Dentz 
18900a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18910a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1892fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
1893daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1894daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
18950a708f8fSGustavo F. Padovan 
18960952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
18970a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
18980a708f8fSGustavo F. Padovan 		kfree_skb(skb);
18990a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19000a708f8fSGustavo F. Padovan 	}
19010a708f8fSGustavo F. Padovan 	return skb;
19020a708f8fSGustavo F. Padovan }
19030a708f8fSGustavo F. Padovan 
19045e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
19055e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19065e59b791SLuiz Augusto von Dentz 						u32 priority)
19070a708f8fSGustavo F. Padovan {
19088c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19090a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1910f2ba7faeSGustavo Padovan 	int err, count;
19110a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19120a708f8fSGustavo F. Padovan 
19136d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19140a708f8fSGustavo F. Padovan 
1915f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
19162f7719ceSAndrei Emeltchenko 
1917f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
191890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
191990338947SGustavo Padovan 	if (IS_ERR(skb))
192090338947SGustavo Padovan 		return skb;
19210a708f8fSGustavo F. Padovan 
19225e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19235e59b791SLuiz Augusto von Dentz 
19240a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19250a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1926fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19276ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
19280a708f8fSGustavo F. Padovan 
19290952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19300a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19310a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19320a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19330a708f8fSGustavo F. Padovan 	}
19340a708f8fSGustavo F. Padovan 	return skb;
19350a708f8fSGustavo F. Padovan }
19360a708f8fSGustavo F. Padovan 
1937ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1938ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
193994122bbeSMat Martineau 						u16 sdulen)
19400a708f8fSGustavo F. Padovan {
19418c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19420a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1943e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
19440a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19450a708f8fSGustavo F. Padovan 
19466d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19470a708f8fSGustavo F. Padovan 
19480a708f8fSGustavo F. Padovan 	if (!conn)
19490a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
19500a708f8fSGustavo F. Padovan 
1951e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1952e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1953e4ca6d98SAndrei Emeltchenko 	else
1954e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1955e4ca6d98SAndrei Emeltchenko 
19560a708f8fSGustavo F. Padovan 	if (sdulen)
195703a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
19580a708f8fSGustavo F. Padovan 
195947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
196003a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
19610a708f8fSGustavo F. Padovan 
19620a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19632f7719ceSAndrei Emeltchenko 
19642f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
196590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
196690338947SGustavo Padovan 	if (IS_ERR(skb))
196790338947SGustavo Padovan 		return skb;
19680a708f8fSGustavo F. Padovan 
19690a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19700a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1971fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19720a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
197388843ab0SAndrei Emeltchenko 
197494122bbeSMat Martineau 	__put_control(chan, 0, skb_put(skb, __ctrl_size(chan)));
197588843ab0SAndrei Emeltchenko 
19760a708f8fSGustavo F. Padovan 	if (sdulen)
197703a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
19780a708f8fSGustavo F. Padovan 
19790952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19800a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19810a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19820a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19830a708f8fSGustavo F. Padovan 	}
19840a708f8fSGustavo F. Padovan 
198547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
198603a51213SAndrei Emeltchenko 		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
19870a708f8fSGustavo F. Padovan 
19883ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
19890a708f8fSGustavo F. Padovan 	return skb;
19900a708f8fSGustavo F. Padovan }
19910a708f8fSGustavo F. Padovan 
199294122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
199394122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
199494122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
19950a708f8fSGustavo F. Padovan {
19960a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
199794122bbeSMat Martineau 	u16 sdu_len;
199894122bbeSMat Martineau 	size_t pdu_len;
199994122bbeSMat Martineau 	int err = 0;
200094122bbeSMat Martineau 	u8 sar;
20010a708f8fSGustavo F. Padovan 
200294122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
20030a708f8fSGustavo F. Padovan 
200494122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
200594122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
200694122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
200794122bbeSMat Martineau 	 */
200894122bbeSMat Martineau 
200994122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
201094122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
201194122bbeSMat Martineau 
201294122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
201394122bbeSMat Martineau 
201494122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
201594122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
201694122bbeSMat Martineau 
201794122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
201894122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
201994122bbeSMat Martineau 
202094122bbeSMat Martineau 	if (len <= pdu_len) {
202194122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
202294122bbeSMat Martineau 		sdu_len = 0;
202394122bbeSMat Martineau 		pdu_len = len;
202494122bbeSMat Martineau 	} else {
202594122bbeSMat Martineau 		sar = L2CAP_SAR_START;
202694122bbeSMat Martineau 		sdu_len = len;
202794122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
202894122bbeSMat Martineau 	}
20290a708f8fSGustavo F. Padovan 
20300a708f8fSGustavo F. Padovan 	while (len > 0) {
203194122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
20320a708f8fSGustavo F. Padovan 
20330a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
203494122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
20350a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
20360a708f8fSGustavo F. Padovan 		}
20370a708f8fSGustavo F. Padovan 
203894122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
203994122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
20400a708f8fSGustavo F. Padovan 
204194122bbeSMat Martineau 		len -= pdu_len;
204294122bbeSMat Martineau 		if (sdu_len) {
204394122bbeSMat Martineau 			sdu_len = 0;
204494122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
204594122bbeSMat Martineau 		}
204694122bbeSMat Martineau 
204794122bbeSMat Martineau 		if (len <= pdu_len) {
204894122bbeSMat Martineau 			sar = L2CAP_SAR_END;
204994122bbeSMat Martineau 			pdu_len = len;
205094122bbeSMat Martineau 		} else {
205194122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
205294122bbeSMat Martineau 		}
205394122bbeSMat Martineau 	}
205494122bbeSMat Martineau 
205594122bbeSMat Martineau 	return err;
20560a708f8fSGustavo F. Padovan }
20570a708f8fSGustavo F. Padovan 
20585e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
20595e59b791SLuiz Augusto von Dentz 								u32 priority)
20609a91a04aSGustavo F. Padovan {
20619a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
20629a91a04aSGustavo F. Padovan 	int err;
206394122bbeSMat Martineau 	struct sk_buff_head seg_queue;
20649a91a04aSGustavo F. Padovan 
20659a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2066715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
20675e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
20689a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20699a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20709a91a04aSGustavo F. Padovan 
20719a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20729a91a04aSGustavo F. Padovan 		return len;
20739a91a04aSGustavo F. Padovan 	}
20749a91a04aSGustavo F. Padovan 
20759a91a04aSGustavo F. Padovan 	switch (chan->mode) {
20769a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
20779a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
20789a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
20799a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
20809a91a04aSGustavo F. Padovan 
20819a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
20825e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
20839a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20849a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20859a91a04aSGustavo F. Padovan 
20869a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20879a91a04aSGustavo F. Padovan 		err = len;
20889a91a04aSGustavo F. Padovan 		break;
20899a91a04aSGustavo F. Padovan 
20909a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20919a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
209294122bbeSMat Martineau 		/* Check outgoing MTU */
209394122bbeSMat Martineau 		if (len > chan->omtu) {
209494122bbeSMat Martineau 			err = -EMSGSIZE;
20959a91a04aSGustavo F. Padovan 			break;
20969a91a04aSGustavo F. Padovan 		}
20979a91a04aSGustavo F. Padovan 
209894122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
209994122bbeSMat Martineau 
210094122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
210194122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
210294122bbeSMat Martineau 		 * allocation.
210394122bbeSMat Martineau 		 */
210494122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
210594122bbeSMat Martineau 
210694122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
210794122bbeSMat Martineau 		 * check that it is still connected.
210894122bbeSMat Martineau 		 */
210994122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
211094122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
211194122bbeSMat Martineau 			err = -ENOTCONN;
21129a91a04aSGustavo F. Padovan 		}
21139a91a04aSGustavo F. Padovan 
211494122bbeSMat Martineau 		if (err)
211594122bbeSMat Martineau 			break;
211694122bbeSMat Martineau 
2117577cfaebSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM && chan->tx_send_head == NULL)
2118577cfaebSMat Martineau 			chan->tx_send_head = seg_queue.next;
211994122bbeSMat Martineau 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2120577cfaebSMat Martineau 
212194122bbeSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
21229a91a04aSGustavo F. Padovan 			err = l2cap_ertm_send(chan);
212394122bbeSMat Martineau 		else
212494122bbeSMat Martineau 			l2cap_streaming_send(chan);
212594122bbeSMat Martineau 
21269a91a04aSGustavo F. Padovan 		if (err >= 0)
21279a91a04aSGustavo F. Padovan 			err = len;
21289a91a04aSGustavo F. Padovan 
212994122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
213094122bbeSMat Martineau 		 * seg_queue and need to be purged.
213194122bbeSMat Martineau 		 */
213294122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
21339a91a04aSGustavo F. Padovan 		break;
21349a91a04aSGustavo F. Padovan 
21359a91a04aSGustavo F. Padovan 	default:
21369a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
21379a91a04aSGustavo F. Padovan 		err = -EBADFD;
21389a91a04aSGustavo F. Padovan 	}
21399a91a04aSGustavo F. Padovan 
21409a91a04aSGustavo F. Padovan 	return err;
21419a91a04aSGustavo F. Padovan }
21429a91a04aSGustavo F. Padovan 
21430a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
21440a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
21450a708f8fSGustavo F. Padovan {
21460a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
214748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
21480a708f8fSGustavo F. Padovan 
21490a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
21500a708f8fSGustavo F. Padovan 
21513df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
21523d57dc68SGustavo F. Padovan 
21533df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
215448454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2155715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
21560a708f8fSGustavo F. Padovan 			continue;
21570a708f8fSGustavo F. Padovan 
21580a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
21590a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
21600a708f8fSGustavo F. Padovan 			continue;
21610a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
21620a708f8fSGustavo F. Padovan 		if (!nskb)
21630a708f8fSGustavo F. Padovan 			continue;
21640a708f8fSGustavo F. Padovan 
216523070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
21660a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
21670a708f8fSGustavo F. Padovan 	}
21683d57dc68SGustavo F. Padovan 
21693df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
21700a708f8fSGustavo F. Padovan }
21710a708f8fSGustavo F. Padovan 
21720a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
21730a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
21740a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
21750a708f8fSGustavo F. Padovan {
21760a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
21770a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
21780a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
21790a708f8fSGustavo F. Padovan 	int len, count;
21800a708f8fSGustavo F. Padovan 
21810a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
21820a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
21830a708f8fSGustavo F. Padovan 
21840a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
21850a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
21860a708f8fSGustavo F. Padovan 
21870a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
21880a708f8fSGustavo F. Padovan 	if (!skb)
21890a708f8fSGustavo F. Padovan 		return NULL;
21900a708f8fSGustavo F. Padovan 
21910a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
21920a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
21933300d9a9SClaudio Takahasi 
21943300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
21953300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
21963300d9a9SClaudio Takahasi 	else
21970a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
21980a708f8fSGustavo F. Padovan 
21990a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
22000a708f8fSGustavo F. Padovan 	cmd->code  = code;
22010a708f8fSGustavo F. Padovan 	cmd->ident = ident;
22020a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
22030a708f8fSGustavo F. Padovan 
22040a708f8fSGustavo F. Padovan 	if (dlen) {
22050a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
22060a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
22070a708f8fSGustavo F. Padovan 		data += count;
22080a708f8fSGustavo F. Padovan 	}
22090a708f8fSGustavo F. Padovan 
22100a708f8fSGustavo F. Padovan 	len -= skb->len;
22110a708f8fSGustavo F. Padovan 
22120a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
22130a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
22140a708f8fSGustavo F. Padovan 	while (len) {
22150a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
22160a708f8fSGustavo F. Padovan 
22170a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
22180a708f8fSGustavo F. Padovan 		if (!*frag)
22190a708f8fSGustavo F. Padovan 			goto fail;
22200a708f8fSGustavo F. Padovan 
22210a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
22220a708f8fSGustavo F. Padovan 
22230a708f8fSGustavo F. Padovan 		len  -= count;
22240a708f8fSGustavo F. Padovan 		data += count;
22250a708f8fSGustavo F. Padovan 
22260a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
22270a708f8fSGustavo F. Padovan 	}
22280a708f8fSGustavo F. Padovan 
22290a708f8fSGustavo F. Padovan 	return skb;
22300a708f8fSGustavo F. Padovan 
22310a708f8fSGustavo F. Padovan fail:
22320a708f8fSGustavo F. Padovan 	kfree_skb(skb);
22330a708f8fSGustavo F. Padovan 	return NULL;
22340a708f8fSGustavo F. Padovan }
22350a708f8fSGustavo F. Padovan 
22360a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
22370a708f8fSGustavo F. Padovan {
22380a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22390a708f8fSGustavo F. Padovan 	int len;
22400a708f8fSGustavo F. Padovan 
22410a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
22420a708f8fSGustavo F. Padovan 	*ptr += len;
22430a708f8fSGustavo F. Padovan 
22440a708f8fSGustavo F. Padovan 	*type = opt->type;
22450a708f8fSGustavo F. Padovan 	*olen = opt->len;
22460a708f8fSGustavo F. Padovan 
22470a708f8fSGustavo F. Padovan 	switch (opt->len) {
22480a708f8fSGustavo F. Padovan 	case 1:
22490a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
22500a708f8fSGustavo F. Padovan 		break;
22510a708f8fSGustavo F. Padovan 
22520a708f8fSGustavo F. Padovan 	case 2:
22530a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
22540a708f8fSGustavo F. Padovan 		break;
22550a708f8fSGustavo F. Padovan 
22560a708f8fSGustavo F. Padovan 	case 4:
22570a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
22580a708f8fSGustavo F. Padovan 		break;
22590a708f8fSGustavo F. Padovan 
22600a708f8fSGustavo F. Padovan 	default:
22610a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
22620a708f8fSGustavo F. Padovan 		break;
22630a708f8fSGustavo F. Padovan 	}
22640a708f8fSGustavo F. Padovan 
22650a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
22660a708f8fSGustavo F. Padovan 	return len;
22670a708f8fSGustavo F. Padovan }
22680a708f8fSGustavo F. Padovan 
22690a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
22700a708f8fSGustavo F. Padovan {
22710a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22720a708f8fSGustavo F. Padovan 
22730a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
22740a708f8fSGustavo F. Padovan 
22750a708f8fSGustavo F. Padovan 	opt->type = type;
22760a708f8fSGustavo F. Padovan 	opt->len  = len;
22770a708f8fSGustavo F. Padovan 
22780a708f8fSGustavo F. Padovan 	switch (len) {
22790a708f8fSGustavo F. Padovan 	case 1:
22800a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
22810a708f8fSGustavo F. Padovan 		break;
22820a708f8fSGustavo F. Padovan 
22830a708f8fSGustavo F. Padovan 	case 2:
22840a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
22850a708f8fSGustavo F. Padovan 		break;
22860a708f8fSGustavo F. Padovan 
22870a708f8fSGustavo F. Padovan 	case 4:
22880a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
22890a708f8fSGustavo F. Padovan 		break;
22900a708f8fSGustavo F. Padovan 
22910a708f8fSGustavo F. Padovan 	default:
22920a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
22930a708f8fSGustavo F. Padovan 		break;
22940a708f8fSGustavo F. Padovan 	}
22950a708f8fSGustavo F. Padovan 
22960a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
22970a708f8fSGustavo F. Padovan }
22980a708f8fSGustavo F. Padovan 
2299f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2300f89cef09SAndrei Emeltchenko {
2301f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2302f89cef09SAndrei Emeltchenko 
2303f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2304f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2305f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2306f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2307f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2308f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2309f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2310f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2311f89cef09SAndrei Emeltchenko 		break;
2312f89cef09SAndrei Emeltchenko 
2313f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2314f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2315f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2316f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2317f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2318f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2319f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2320f89cef09SAndrei Emeltchenko 		break;
2321f89cef09SAndrei Emeltchenko 
2322f89cef09SAndrei Emeltchenko 	default:
2323f89cef09SAndrei Emeltchenko 		return;
2324f89cef09SAndrei Emeltchenko 	}
2325f89cef09SAndrei Emeltchenko 
2326f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2327f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2328f89cef09SAndrei Emeltchenko }
2329f89cef09SAndrei Emeltchenko 
2330721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
23310a708f8fSGustavo F. Padovan {
2332721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2333721c4181SGustavo F. Padovan 							ack_timer.work);
23340a708f8fSGustavo F. Padovan 
23352fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
23362fb9b3d4SGustavo F. Padovan 
23376be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
23386be36555SAndrei Emeltchenko 
2339b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
23406be36555SAndrei Emeltchenko 
23416be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
234209bfb2eeSSzymon Janc 
234309bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
23440a708f8fSGustavo F. Padovan }
23450a708f8fSGustavo F. Padovan 
23463c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
23470a708f8fSGustavo F. Padovan {
23483c588192SMat Martineau 	int err;
23493c588192SMat Martineau 
2350105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2351105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
235242e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
23536a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
235442e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
23556a026610SGustavo F. Padovan 	chan->num_acked = 0;
23566a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2357105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2358105bdf9eSMat Martineau 	chan->sdu = NULL;
2359105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2360105bdf9eSMat Martineau 	chan->sdu_len = 0;
2361105bdf9eSMat Martineau 
2362d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2363d34c34fbSMat Martineau 
2364105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2365105bdf9eSMat Martineau 		return 0;
2366105bdf9eSMat Martineau 
2367105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2368105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
23690a708f8fSGustavo F. Padovan 
2370721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2371721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2372721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
23730a708f8fSGustavo F. Padovan 
2374f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
23750a708f8fSGustavo F. Padovan 
237639d5a3eeSGustavo F. Padovan 	INIT_LIST_HEAD(&chan->srej_l);
23773c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
23783c588192SMat Martineau 	if (err < 0)
23793c588192SMat Martineau 		return err;
23803c588192SMat Martineau 
23813c588192SMat Martineau 	return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
23820a708f8fSGustavo F. Padovan }
23830a708f8fSGustavo F. Padovan 
23840a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
23850a708f8fSGustavo F. Padovan {
23860a708f8fSGustavo F. Padovan 	switch (mode) {
23870a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23880a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
23890a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
23900a708f8fSGustavo F. Padovan 			return mode;
23910a708f8fSGustavo F. Padovan 		/* fall through */
23920a708f8fSGustavo F. Padovan 	default:
23930a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
23940a708f8fSGustavo F. Padovan 	}
23950a708f8fSGustavo F. Padovan }
23960a708f8fSGustavo F. Padovan 
23976327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
23986327eb98SAndrei Emeltchenko {
23996327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
24006327eb98SAndrei Emeltchenko }
24016327eb98SAndrei Emeltchenko 
2402f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2403f89cef09SAndrei Emeltchenko {
2404f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2405f89cef09SAndrei Emeltchenko }
2406f89cef09SAndrei Emeltchenko 
24076327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
24086327eb98SAndrei Emeltchenko {
24096327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2410836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
24116327eb98SAndrei Emeltchenko 		/* use extended control field */
24126327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2413836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2414836be934SAndrei Emeltchenko 	} else {
24156327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
24166327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2417836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2418836be934SAndrei Emeltchenko 	}
24196327eb98SAndrei Emeltchenko }
24206327eb98SAndrei Emeltchenko 
2421710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
24220a708f8fSGustavo F. Padovan {
24230a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
24240c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
24250a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2426c8f79162SAndrei Emeltchenko 	u16 size;
24270a708f8fSGustavo F. Padovan 
242849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
24290a708f8fSGustavo F. Padovan 
243073ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
24310a708f8fSGustavo F. Padovan 		goto done;
24320a708f8fSGustavo F. Padovan 
24330c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
24340a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
24350a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2436c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
24370a708f8fSGustavo F. Padovan 			break;
24380a708f8fSGustavo F. Padovan 
2439f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2440f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2441f89cef09SAndrei Emeltchenko 
24420a708f8fSGustavo F. Padovan 		/* fall through */
24430a708f8fSGustavo F. Padovan 	default:
24448c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
24450a708f8fSGustavo F. Padovan 		break;
24460a708f8fSGustavo F. Padovan 	}
24470a708f8fSGustavo F. Padovan 
24480a708f8fSGustavo F. Padovan done:
24490c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
24500c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
24510a708f8fSGustavo F. Padovan 
24520c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
24530a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
24548c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
24558c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
24560a708f8fSGustavo F. Padovan 			break;
24570a708f8fSGustavo F. Padovan 
24580a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
24590a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
24600a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
24610a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24620a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
24630a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
24640a708f8fSGustavo F. Padovan 
24650a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24660a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24670a708f8fSGustavo F. Padovan 		break;
24680a708f8fSGustavo F. Padovan 
24690a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
24700a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
247147d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
24720a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24730a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2474c8f79162SAndrei Emeltchenko 
2475c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2476c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2477c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2478c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2479c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
24800a708f8fSGustavo F. Padovan 
24816327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
24826327eb98SAndrei Emeltchenko 
24836327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
24846327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
24850a708f8fSGustavo F. Padovan 
24860a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24870a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24880a708f8fSGustavo F. Padovan 
2489f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2490f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2491f89cef09SAndrei Emeltchenko 
24928c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
24930a708f8fSGustavo F. Padovan 			break;
24940a708f8fSGustavo F. Padovan 
249547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2496c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
249747d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
249847d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
24990a708f8fSGustavo F. Padovan 		}
25006327eb98SAndrei Emeltchenko 
25016327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
25026327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
25036327eb98SAndrei Emeltchenko 								chan->tx_win);
25040a708f8fSGustavo F. Padovan 		break;
25050a708f8fSGustavo F. Padovan 
25060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
25070a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
25080a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
25090a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
25100a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
25110a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2512c8f79162SAndrei Emeltchenko 
2513c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2514c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2515c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2516c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2517c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
25180a708f8fSGustavo F. Padovan 
25190a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
25200a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
25210a708f8fSGustavo F. Padovan 
2522f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2523f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2524f89cef09SAndrei Emeltchenko 
25258c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
25260a708f8fSGustavo F. Padovan 			break;
25270a708f8fSGustavo F. Padovan 
252847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2529c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
253047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
253147d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
25320a708f8fSGustavo F. Padovan 		}
25330a708f8fSGustavo F. Padovan 		break;
25340a708f8fSGustavo F. Padovan 	}
25350a708f8fSGustavo F. Padovan 
2536fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
25370a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
25380a708f8fSGustavo F. Padovan 
25390a708f8fSGustavo F. Padovan 	return ptr - data;
25400a708f8fSGustavo F. Padovan }
25410a708f8fSGustavo F. Padovan 
254273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
25430a708f8fSGustavo F. Padovan {
25440a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
25450a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
254673ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
254773ffa904SGustavo F. Padovan 	int len = chan->conf_len;
25480a708f8fSGustavo F. Padovan 	int type, hint, olen;
25490a708f8fSGustavo F. Padovan 	unsigned long val;
25500a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
255142dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
255242dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
25530a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
25540a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2555c8f79162SAndrei Emeltchenko 	u16 size;
25560a708f8fSGustavo F. Padovan 
255773ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
25580a708f8fSGustavo F. Padovan 
25590a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
25600a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
25610a708f8fSGustavo F. Padovan 
25620a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
25630a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
25640a708f8fSGustavo F. Padovan 
25650a708f8fSGustavo F. Padovan 		switch (type) {
25660a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
25670a708f8fSGustavo F. Padovan 			mtu = val;
25680a708f8fSGustavo F. Padovan 			break;
25690a708f8fSGustavo F. Padovan 
25700a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
25710c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
25720a708f8fSGustavo F. Padovan 			break;
25730a708f8fSGustavo F. Padovan 
25740a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
25750a708f8fSGustavo F. Padovan 			break;
25760a708f8fSGustavo F. Padovan 
25770a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
25780a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
25790a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
25800a708f8fSGustavo F. Padovan 			break;
25810a708f8fSGustavo F. Padovan 
25820a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
25830a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2584c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
258542dceae2SAndrei Emeltchenko 			break;
25860a708f8fSGustavo F. Padovan 
258742dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
258842dceae2SAndrei Emeltchenko 			remote_efs = 1;
258942dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
259042dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
25910a708f8fSGustavo F. Padovan 			break;
25920a708f8fSGustavo F. Padovan 
25936327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
25946327eb98SAndrei Emeltchenko 			if (!enable_hs)
25956327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
25966327eb98SAndrei Emeltchenko 
25976327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
25986327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2599836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
26006327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
26010a708f8fSGustavo F. Padovan 			break;
26020a708f8fSGustavo F. Padovan 
26030a708f8fSGustavo F. Padovan 		default:
26040a708f8fSGustavo F. Padovan 			if (hint)
26050a708f8fSGustavo F. Padovan 				break;
26060a708f8fSGustavo F. Padovan 
26070a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
26080a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
26090a708f8fSGustavo F. Padovan 			break;
26100a708f8fSGustavo F. Padovan 		}
26110a708f8fSGustavo F. Padovan 	}
26120a708f8fSGustavo F. Padovan 
261373ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
26140a708f8fSGustavo F. Padovan 		goto done;
26150a708f8fSGustavo F. Padovan 
26160c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
26170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
26180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2619c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
26200c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
26218c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
26220a708f8fSGustavo F. Padovan 			break;
26230a708f8fSGustavo F. Padovan 		}
26240a708f8fSGustavo F. Padovan 
262542dceae2SAndrei Emeltchenko 		if (remote_efs) {
262642dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
262742dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
262842dceae2SAndrei Emeltchenko 			else
262942dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
263042dceae2SAndrei Emeltchenko 		}
263142dceae2SAndrei Emeltchenko 
26320c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
26330a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
26340a708f8fSGustavo F. Padovan 
26350a708f8fSGustavo F. Padovan 		break;
26360a708f8fSGustavo F. Padovan 	}
26370a708f8fSGustavo F. Padovan 
26380a708f8fSGustavo F. Padovan done:
26390c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
26400a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
26410c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
26420a708f8fSGustavo F. Padovan 
264373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
26440a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
26450a708f8fSGustavo F. Padovan 
26460a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26470a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26480a708f8fSGustavo F. Padovan 	}
26490a708f8fSGustavo F. Padovan 
26500a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
26510a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
26520a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
26530a708f8fSGustavo F. Padovan 
26540a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
26550a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
26560a708f8fSGustavo F. Padovan 		else {
26570c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2658c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
26590a708f8fSGustavo F. Padovan 		}
26600c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
26610a708f8fSGustavo F. Padovan 
266242dceae2SAndrei Emeltchenko 		if (remote_efs) {
266342dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
266442dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
266542dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
266642dceae2SAndrei Emeltchenko 
266742dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
266842dceae2SAndrei Emeltchenko 
266942dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
267042dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
267142dceae2SAndrei Emeltchenko 
267242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
267342dceae2SAndrei Emeltchenko 							sizeof(efs),
267442dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
26750e8b207eSAndrei Emeltchenko 			} else {
26763e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
26770e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
26780e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
267942dceae2SAndrei Emeltchenko 			}
268042dceae2SAndrei Emeltchenko 		}
268142dceae2SAndrei Emeltchenko 
26820a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
26830a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
268447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2685c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26860a708f8fSGustavo F. Padovan 			break;
26870a708f8fSGustavo F. Padovan 
26880a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
26896327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
26902c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
26916327eb98SAndrei Emeltchenko 			else
26926327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
26936327eb98SAndrei Emeltchenko 
26942c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
26950a708f8fSGustavo F. Padovan 
2696c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2697c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2698c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2699c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2700c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2701c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2702c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
27030a708f8fSGustavo F. Padovan 
27040a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
27054fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
27060a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
27074fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
27080a708f8fSGustavo F. Padovan 
2709c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
27100a708f8fSGustavo F. Padovan 
27110a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27120a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27130a708f8fSGustavo F. Padovan 
271442dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
271542dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
271642dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
271742dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
271842dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
271942dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
272042dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
272142dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
272242dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
272342dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
272442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
272542dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
272642dceae2SAndrei Emeltchenko 			}
27270a708f8fSGustavo F. Padovan 			break;
27280a708f8fSGustavo F. Padovan 
27290a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2730c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2731c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2732c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2733c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2734c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2735c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2736c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
27370a708f8fSGustavo F. Padovan 
2738c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
27390a708f8fSGustavo F. Padovan 
27400a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27410a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27420a708f8fSGustavo F. Padovan 
27430a708f8fSGustavo F. Padovan 			break;
27440a708f8fSGustavo F. Padovan 
27450a708f8fSGustavo F. Padovan 		default:
27460a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
27470a708f8fSGustavo F. Padovan 
27480a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
27490c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
27500a708f8fSGustavo F. Padovan 		}
27510a708f8fSGustavo F. Padovan 
27520a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2753c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
27540a708f8fSGustavo F. Padovan 	}
2755fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
27560a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
27570a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
27580a708f8fSGustavo F. Padovan 
27590a708f8fSGustavo F. Padovan 	return ptr - data;
27600a708f8fSGustavo F. Padovan }
27610a708f8fSGustavo F. Padovan 
2762b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
27630a708f8fSGustavo F. Padovan {
27640a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
27650a708f8fSGustavo F. Padovan 	void *ptr = req->data;
27660a708f8fSGustavo F. Padovan 	int type, olen;
27670a708f8fSGustavo F. Padovan 	unsigned long val;
276836e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
276966af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
27700a708f8fSGustavo F. Padovan 
2771fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
27720a708f8fSGustavo F. Padovan 
27730a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
27740a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
27750a708f8fSGustavo F. Padovan 
27760a708f8fSGustavo F. Padovan 		switch (type) {
27770a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
27780a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
27790a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
27800c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
27810a708f8fSGustavo F. Padovan 			} else
27820c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
27830c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
27840a708f8fSGustavo F. Padovan 			break;
27850a708f8fSGustavo F. Padovan 
27860a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
27870c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
27880a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
27890c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
27900a708f8fSGustavo F. Padovan 			break;
27910a708f8fSGustavo F. Padovan 
27920a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
27930a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
27940a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
27950a708f8fSGustavo F. Padovan 
2796c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
27970c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
27980a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
27990a708f8fSGustavo F. Padovan 
280047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
28010a708f8fSGustavo F. Padovan 
28020a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
28030a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
28040a708f8fSGustavo F. Padovan 			break;
28056327eb98SAndrei Emeltchenko 
28066327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
28076327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
28086327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
28093e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
28103e6b3b95SGustavo F. Padovan 							chan->tx_win);
28116327eb98SAndrei Emeltchenko 			break;
281266af7aafSAndrei Emeltchenko 
281366af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
281466af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
281566af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
281666af7aafSAndrei Emeltchenko 
281766af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
281866af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
281966af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
282066af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
282166af7aafSAndrei Emeltchenko 
282266af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
282366af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
282466af7aafSAndrei Emeltchenko 			break;
28250a708f8fSGustavo F. Padovan 		}
28260a708f8fSGustavo F. Padovan 	}
28270a708f8fSGustavo F. Padovan 
28280c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
28290a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
28300a708f8fSGustavo F. Padovan 
28310c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
28320a708f8fSGustavo F. Padovan 
28330e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
28340a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
28350a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
283647d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
283747d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
283847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
283966af7aafSAndrei Emeltchenko 
284066af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
284166af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
284266af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
284366af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
284466af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
284566af7aafSAndrei Emeltchenko 				chan->local_flush_to =
284666af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
284766af7aafSAndrei Emeltchenko 			}
28480a708f8fSGustavo F. Padovan 			break;
284966af7aafSAndrei Emeltchenko 
28500a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
285147d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28520a708f8fSGustavo F. Padovan 		}
28530a708f8fSGustavo F. Padovan 	}
28540a708f8fSGustavo F. Padovan 
2855fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
28560a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
28570a708f8fSGustavo F. Padovan 
28580a708f8fSGustavo F. Padovan 	return ptr - data;
28590a708f8fSGustavo F. Padovan }
28600a708f8fSGustavo F. Padovan 
2861fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
28620a708f8fSGustavo F. Padovan {
28630a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
28640a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
28650a708f8fSGustavo F. Padovan 
2866fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
28670a708f8fSGustavo F. Padovan 
2868fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
28690a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
28700a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
28710a708f8fSGustavo F. Padovan 
28720a708f8fSGustavo F. Padovan 	return ptr - data;
28730a708f8fSGustavo F. Padovan }
28740a708f8fSGustavo F. Padovan 
28758c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
2876710f9b0aSGustavo F. Padovan {
2877710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
28788c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
2879710f9b0aSGustavo F. Padovan 	u8 buf[128];
2880710f9b0aSGustavo F. Padovan 
2881fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
2882fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
2883710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2884710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2885710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
2886710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2887710f9b0aSGustavo F. Padovan 
2888c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
2889710f9b0aSGustavo F. Padovan 		return;
2890710f9b0aSGustavo F. Padovan 
2891710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2892710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
2893710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
2894710f9b0aSGustavo F. Padovan }
2895710f9b0aSGustavo F. Padovan 
289647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
28970a708f8fSGustavo F. Padovan {
28980a708f8fSGustavo F. Padovan 	int type, olen;
28990a708f8fSGustavo F. Padovan 	unsigned long val;
29000a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
29010a708f8fSGustavo F. Padovan 
290247d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
29030a708f8fSGustavo F. Padovan 
29040c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
29050a708f8fSGustavo F. Padovan 		return;
29060a708f8fSGustavo F. Padovan 
29070a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29080a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
29090a708f8fSGustavo F. Padovan 
29100a708f8fSGustavo F. Padovan 		switch (type) {
29110a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29120a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29130a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
29140a708f8fSGustavo F. Padovan 			goto done;
29150a708f8fSGustavo F. Padovan 		}
29160a708f8fSGustavo F. Padovan 	}
29170a708f8fSGustavo F. Padovan 
291836e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
291936e999a8SMat Martineau 	 * did not send an RFC option.
292036e999a8SMat Martineau 	 */
292136e999a8SMat Martineau 	rfc.mode = chan->mode;
292236e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
292336e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
292436e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
292536e999a8SMat Martineau 
292636e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
292736e999a8SMat Martineau 
29280a708f8fSGustavo F. Padovan done:
29290a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
29300a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
293147d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
293247d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
293347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
29340a708f8fSGustavo F. Padovan 		break;
29350a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
293647d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
29370a708f8fSGustavo F. Padovan 	}
29380a708f8fSGustavo F. Padovan }
29390a708f8fSGustavo F. Padovan 
29400a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29410a708f8fSGustavo F. Padovan {
2942e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
29430a708f8fSGustavo F. Padovan 
2944e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
29450a708f8fSGustavo F. Padovan 		return 0;
29460a708f8fSGustavo F. Padovan 
29470a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
29480a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
294917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
29500a708f8fSGustavo F. Padovan 
29510a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
29520a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
29530a708f8fSGustavo F. Padovan 
29540a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
29550a708f8fSGustavo F. Padovan 	}
29560a708f8fSGustavo F. Padovan 
29570a708f8fSGustavo F. Padovan 	return 0;
29580a708f8fSGustavo F. Padovan }
29590a708f8fSGustavo F. Padovan 
29600a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29610a708f8fSGustavo F. Padovan {
29620a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
29630a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
296423691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
29650a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
29660a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
29670a708f8fSGustavo F. Padovan 
29680a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
29690a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
29700a708f8fSGustavo F. Padovan 
2971097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
29720a708f8fSGustavo F. Padovan 
29730a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
2974c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
297523691d75SGustavo F. Padovan 	if (!pchan) {
29760a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
29770a708f8fSGustavo F. Padovan 		goto sendresp;
29780a708f8fSGustavo F. Padovan 	}
29790a708f8fSGustavo F. Padovan 
298023691d75SGustavo F. Padovan 	parent = pchan->sk;
298123691d75SGustavo F. Padovan 
29823df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2983aa2ac881SGustavo F. Padovan 	lock_sock(parent);
29840a708f8fSGustavo F. Padovan 
29850a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
29860a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
29870a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
29889f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
29890a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
29900a708f8fSGustavo F. Padovan 		goto response;
29910a708f8fSGustavo F. Padovan 	}
29920a708f8fSGustavo F. Padovan 
29930a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
29940a708f8fSGustavo F. Padovan 
29950a708f8fSGustavo F. Padovan 	/* Check for backlog size */
29960a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
29970a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
29980a708f8fSGustavo F. Padovan 		goto response;
29990a708f8fSGustavo F. Padovan 	}
30000a708f8fSGustavo F. Padovan 
300180808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
300280808e43SGustavo F. Padovan 	if (!chan)
30030a708f8fSGustavo F. Padovan 		goto response;
30040a708f8fSGustavo F. Padovan 
300580808e43SGustavo F. Padovan 	sk = chan->sk;
300680808e43SGustavo F. Padovan 
30070a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3008baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
30090a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3010ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
30110a708f8fSGustavo F. Padovan 		goto response;
30120a708f8fSGustavo F. Padovan 	}
30130a708f8fSGustavo F. Padovan 
30140a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
30150a708f8fSGustavo F. Padovan 
30160a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
30170a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3018fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3019fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
30200a708f8fSGustavo F. Padovan 
3021d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3022d1010240SGustavo F. Padovan 
30236be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
302448454079SGustavo F. Padovan 
3025fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
30260a708f8fSGustavo F. Padovan 
3027c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
30280a708f8fSGustavo F. Padovan 
3029fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
30300a708f8fSGustavo F. Padovan 
30310a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3032d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
30330a708f8fSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup) {
30340e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
30350a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
30360a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
30370a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
30380a708f8fSGustavo F. Padovan 			} else {
30390e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
30400a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
30410a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
30420a708f8fSGustavo F. Padovan 			}
30430a708f8fSGustavo F. Padovan 		} else {
30440e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
30450a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
30460a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
30470a708f8fSGustavo F. Padovan 		}
30480a708f8fSGustavo F. Padovan 	} else {
30490e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
30500a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
30510a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
30520a708f8fSGustavo F. Padovan 	}
30530a708f8fSGustavo F. Padovan 
30540a708f8fSGustavo F. Padovan response:
3055aa2ac881SGustavo F. Padovan 	release_sock(parent);
30563df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30570a708f8fSGustavo F. Padovan 
30580a708f8fSGustavo F. Padovan sendresp:
30590a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
30600a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
30610a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
30620a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
30630a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
30640a708f8fSGustavo F. Padovan 
30650a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
30660a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
30670a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
30680a708f8fSGustavo F. Padovan 
30690a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
30700a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
30710a708f8fSGustavo F. Padovan 
3072ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
30730a708f8fSGustavo F. Padovan 
30740a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
30750a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
30760a708f8fSGustavo F. Padovan 	}
30770a708f8fSGustavo F. Padovan 
3078c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
30790a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
30800a708f8fSGustavo F. Padovan 		u8 buf[128];
3081c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
30820a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
308373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
308473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30850a708f8fSGustavo F. Padovan 	}
30860a708f8fSGustavo F. Padovan 
30870a708f8fSGustavo F. Padovan 	return 0;
30880a708f8fSGustavo F. Padovan }
30890a708f8fSGustavo F. Padovan 
30900a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
30910a708f8fSGustavo F. Padovan {
30920a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
30930a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
309448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30950a708f8fSGustavo F. Padovan 	u8 req[128];
30963df91ea2SAndrei Emeltchenko 	int err;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
30990a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
31000a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
31010a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
31020a708f8fSGustavo F. Padovan 
31031b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
31041b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
31050a708f8fSGustavo F. Padovan 
31063df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
31073df91ea2SAndrei Emeltchenko 
31080a708f8fSGustavo F. Padovan 	if (scid) {
31093df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
31103df91ea2SAndrei Emeltchenko 		if (!chan) {
31113df91ea2SAndrei Emeltchenko 			err = -EFAULT;
31123df91ea2SAndrei Emeltchenko 			goto unlock;
31133df91ea2SAndrei Emeltchenko 		}
31140a708f8fSGustavo F. Padovan 	} else {
31153df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
31163df91ea2SAndrei Emeltchenko 		if (!chan) {
31173df91ea2SAndrei Emeltchenko 			err = -EFAULT;
31183df91ea2SAndrei Emeltchenko 			goto unlock;
31193df91ea2SAndrei Emeltchenko 		}
31200a708f8fSGustavo F. Padovan 	}
31210a708f8fSGustavo F. Padovan 
31223df91ea2SAndrei Emeltchenko 	err = 0;
31233df91ea2SAndrei Emeltchenko 
31246be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
312548454079SGustavo F. Padovan 
31260a708f8fSGustavo F. Padovan 	switch (result) {
31270a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
312889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3129fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3130fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3131c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
31320a708f8fSGustavo F. Padovan 
3133c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
31340a708f8fSGustavo F. Padovan 			break;
31350a708f8fSGustavo F. Padovan 
31360a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
313773ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
313873ffa904SGustavo F. Padovan 		chan->num_conf_req++;
31390a708f8fSGustavo F. Padovan 		break;
31400a708f8fSGustavo F. Padovan 
31410a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3142c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
31430a708f8fSGustavo F. Padovan 		break;
31440a708f8fSGustavo F. Padovan 
31450a708f8fSGustavo F. Padovan 	default:
314648454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
31470a708f8fSGustavo F. Padovan 		break;
31480a708f8fSGustavo F. Padovan 	}
31490a708f8fSGustavo F. Padovan 
31506be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
31513df91ea2SAndrei Emeltchenko 
31523df91ea2SAndrei Emeltchenko unlock:
31533df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
31543df91ea2SAndrei Emeltchenko 
31553df91ea2SAndrei Emeltchenko 	return err;
31560a708f8fSGustavo F. Padovan }
31570a708f8fSGustavo F. Padovan 
315847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
31590a708f8fSGustavo F. Padovan {
31600a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
31610a708f8fSGustavo F. Padovan 	 * sides request it.
31620a708f8fSGustavo F. Padovan 	 */
31630c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
316447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3165c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
316647d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
31670a708f8fSGustavo F. Padovan }
31680a708f8fSGustavo F. Padovan 
31690a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
31700a708f8fSGustavo F. Padovan {
31710a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
31720a708f8fSGustavo F. Padovan 	u16 dcid, flags;
31730a708f8fSGustavo F. Padovan 	u8 rsp[64];
317448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
31753c588192SMat Martineau 	int len, err = 0;
31760a708f8fSGustavo F. Padovan 
31770a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
31780a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
31790a708f8fSGustavo F. Padovan 
31800a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
31810a708f8fSGustavo F. Padovan 
3182baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
318348454079SGustavo F. Padovan 	if (!chan)
31840a708f8fSGustavo F. Padovan 		return -ENOENT;
31850a708f8fSGustavo F. Padovan 
31866be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
318748454079SGustavo F. Padovan 
3188033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3189e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
31900a708f8fSGustavo F. Padovan 
3191e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3192e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3193e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3194e2fd318eSIlia Kolomisnky 
31950a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
31960a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
31970a708f8fSGustavo F. Padovan 		goto unlock;
31980a708f8fSGustavo F. Padovan 	}
31990a708f8fSGustavo F. Padovan 
32000a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
32010a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
32027ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
32030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3204fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
32050a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
32060a708f8fSGustavo F. Padovan 		goto unlock;
32070a708f8fSGustavo F. Padovan 	}
32080a708f8fSGustavo F. Padovan 
32090a708f8fSGustavo F. Padovan 	/* Store config. */
321073ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
321173ffa904SGustavo F. Padovan 	chan->conf_len += len;
32120a708f8fSGustavo F. Padovan 
32130a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
32140a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
32150a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3216fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
32170a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
32180a708f8fSGustavo F. Padovan 		goto unlock;
32190a708f8fSGustavo F. Padovan 	}
32200a708f8fSGustavo F. Padovan 
32210a708f8fSGustavo F. Padovan 	/* Complete config. */
322273ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
32230a708f8fSGustavo F. Padovan 	if (len < 0) {
3224e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
32250a708f8fSGustavo F. Padovan 		goto unlock;
32260a708f8fSGustavo F. Padovan 	}
32270a708f8fSGustavo F. Padovan 
32280a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
322973ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
32300a708f8fSGustavo F. Padovan 
32310a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
323273ffa904SGustavo F. Padovan 	chan->conf_len = 0;
32330a708f8fSGustavo F. Padovan 
3234c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
32350a708f8fSGustavo F. Padovan 		goto unlock;
32360a708f8fSGustavo F. Padovan 
3237c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
323847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
32390a708f8fSGustavo F. Padovan 
324089bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
32410a708f8fSGustavo F. Padovan 
3242105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3243105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
32443c588192SMat Martineau 			err = l2cap_ertm_init(chan);
32450a708f8fSGustavo F. Padovan 
32463c588192SMat Martineau 		if (err < 0)
32473c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
32483c588192SMat Martineau 		else
3249cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
32503c588192SMat Martineau 
32510a708f8fSGustavo F. Padovan 		goto unlock;
32520a708f8fSGustavo F. Padovan 	}
32530a708f8fSGustavo F. Padovan 
3254c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
32550a708f8fSGustavo F. Padovan 		u8 buf[64];
32560a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
325773ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
325873ffa904SGustavo F. Padovan 		chan->num_conf_req++;
32590a708f8fSGustavo F. Padovan 	}
32600a708f8fSGustavo F. Padovan 
32610e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
32620e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
32630e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
32640e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
32650e8b207eSAndrei Emeltchenko 
32660e8b207eSAndrei Emeltchenko 		/* check compatibility */
32670e8b207eSAndrei Emeltchenko 
32680e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
32690e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
32700e8b207eSAndrei Emeltchenko 
32710e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
32720e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
32730e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
32740e8b207eSAndrei Emeltchenko 	}
32750e8b207eSAndrei Emeltchenko 
32760a708f8fSGustavo F. Padovan unlock:
32776be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
32783c588192SMat Martineau 	return err;
32790a708f8fSGustavo F. Padovan }
32800a708f8fSGustavo F. Padovan 
32810a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
32820a708f8fSGustavo F. Padovan {
32830a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
32840a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
328548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
328661386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
32873c588192SMat Martineau 	int err = 0;
32880a708f8fSGustavo F. Padovan 
32890a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
32900a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
32910a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
32920a708f8fSGustavo F. Padovan 
329361386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
329461386cbaSAndrei Emeltchenko 	       result, len);
32950a708f8fSGustavo F. Padovan 
3296baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
329748454079SGustavo F. Padovan 	if (!chan)
32980a708f8fSGustavo F. Padovan 		return 0;
32990a708f8fSGustavo F. Padovan 
33006be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
330148454079SGustavo F. Padovan 
33020a708f8fSGustavo F. Padovan 	switch (result) {
33030a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
330447d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
33050e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
33060a708f8fSGustavo F. Padovan 		break;
33070a708f8fSGustavo F. Padovan 
33080e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
33090e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
33100e8b207eSAndrei Emeltchenko 
33110e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
33120e8b207eSAndrei Emeltchenko 			char buf[64];
33130e8b207eSAndrei Emeltchenko 
33140e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
33150e8b207eSAndrei Emeltchenko 								buf, &result);
33160e8b207eSAndrei Emeltchenko 			if (len < 0) {
33170e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33180e8b207eSAndrei Emeltchenko 				goto done;
33190e8b207eSAndrei Emeltchenko 			}
33200e8b207eSAndrei Emeltchenko 
33210e8b207eSAndrei Emeltchenko 			/* check compatibility */
33220e8b207eSAndrei Emeltchenko 
33230e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
33240e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
33250e8b207eSAndrei Emeltchenko 
33260e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
33270e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
33280e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
33290e8b207eSAndrei Emeltchenko 		}
33300e8b207eSAndrei Emeltchenko 		goto done;
33310e8b207eSAndrei Emeltchenko 
33320a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
333373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
33340a708f8fSGustavo F. Padovan 			char req[64];
33350a708f8fSGustavo F. Padovan 
33360a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3337e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33380a708f8fSGustavo F. Padovan 				goto done;
33390a708f8fSGustavo F. Padovan 			}
33400a708f8fSGustavo F. Padovan 
33410a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
33420a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3343b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3344b4450035SGustavo F. Padovan 								req, &result);
33450a708f8fSGustavo F. Padovan 			if (len < 0) {
3346e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33470a708f8fSGustavo F. Padovan 				goto done;
33480a708f8fSGustavo F. Padovan 			}
33490a708f8fSGustavo F. Padovan 
33500a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
33510a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
335273ffa904SGustavo F. Padovan 			chan->num_conf_req++;
33530a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
33540a708f8fSGustavo F. Padovan 				goto done;
33550a708f8fSGustavo F. Padovan 			break;
33560a708f8fSGustavo F. Padovan 		}
33570a708f8fSGustavo F. Padovan 
33580a708f8fSGustavo F. Padovan 	default:
33596be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
33602e0052e4SAndrei Emeltchenko 
3361ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3362e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
33630a708f8fSGustavo F. Padovan 		goto done;
33640a708f8fSGustavo F. Padovan 	}
33650a708f8fSGustavo F. Padovan 
33660a708f8fSGustavo F. Padovan 	if (flags & 0x01)
33670a708f8fSGustavo F. Padovan 		goto done;
33680a708f8fSGustavo F. Padovan 
3369c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
33700a708f8fSGustavo F. Padovan 
3371c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
337247d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
33730a708f8fSGustavo F. Padovan 
337489bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3375105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3376105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
33773c588192SMat Martineau 			err = l2cap_ertm_init(chan);
33780a708f8fSGustavo F. Padovan 
33793c588192SMat Martineau 		if (err < 0)
33803c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
33813c588192SMat Martineau 		else
3382cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
33830a708f8fSGustavo F. Padovan 	}
33840a708f8fSGustavo F. Padovan 
33850a708f8fSGustavo F. Padovan done:
33866be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33873c588192SMat Martineau 	return err;
33880a708f8fSGustavo F. Padovan }
33890a708f8fSGustavo F. Padovan 
33900a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33910a708f8fSGustavo F. Padovan {
33920a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
33930a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
33940a708f8fSGustavo F. Padovan 	u16 dcid, scid;
339548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33960a708f8fSGustavo F. Padovan 	struct sock *sk;
33970a708f8fSGustavo F. Padovan 
33980a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
33990a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
34000a708f8fSGustavo F. Padovan 
34010a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
34020a708f8fSGustavo F. Padovan 
34033df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34043df91ea2SAndrei Emeltchenko 
34053df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
34063df91ea2SAndrei Emeltchenko 	if (!chan) {
34073df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
34080a708f8fSGustavo F. Padovan 		return 0;
34093df91ea2SAndrei Emeltchenko 	}
34100a708f8fSGustavo F. Padovan 
34116be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
34126be36555SAndrei Emeltchenko 
341348454079SGustavo F. Padovan 	sk = chan->sk;
341448454079SGustavo F. Padovan 
3415fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3416fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
34170a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
34180a708f8fSGustavo F. Padovan 
34196be36555SAndrei Emeltchenko 	lock_sock(sk);
34200a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
34216be36555SAndrei Emeltchenko 	release_sock(sk);
34220a708f8fSGustavo F. Padovan 
342361d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
342448454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
34256be36555SAndrei Emeltchenko 
34266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
34270a708f8fSGustavo F. Padovan 
3428ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
342961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
34303df91ea2SAndrei Emeltchenko 
34313df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34323df91ea2SAndrei Emeltchenko 
34330a708f8fSGustavo F. Padovan 	return 0;
34340a708f8fSGustavo F. Padovan }
34350a708f8fSGustavo F. Padovan 
34360a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34370a708f8fSGustavo F. Padovan {
34380a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
34390a708f8fSGustavo F. Padovan 	u16 dcid, scid;
344048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34410a708f8fSGustavo F. Padovan 
34420a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
34430a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
34440a708f8fSGustavo F. Padovan 
34450a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
34460a708f8fSGustavo F. Padovan 
34473df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34483df91ea2SAndrei Emeltchenko 
34493df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
34503df91ea2SAndrei Emeltchenko 	if (!chan) {
34513df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
34520a708f8fSGustavo F. Padovan 		return 0;
34533df91ea2SAndrei Emeltchenko 	}
34540a708f8fSGustavo F. Padovan 
34556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
345648454079SGustavo F. Padovan 
345761d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
345848454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
34596be36555SAndrei Emeltchenko 
34606be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
34610a708f8fSGustavo F. Padovan 
3462ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
346361d6ef3eSMat Martineau 	l2cap_chan_put(chan);
34643df91ea2SAndrei Emeltchenko 
34653df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34663df91ea2SAndrei Emeltchenko 
34670a708f8fSGustavo F. Padovan 	return 0;
34680a708f8fSGustavo F. Padovan }
34690a708f8fSGustavo F. Padovan 
34700a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34710a708f8fSGustavo F. Padovan {
34720a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
34730a708f8fSGustavo F. Padovan 	u16 type;
34740a708f8fSGustavo F. Padovan 
34750a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
34760a708f8fSGustavo F. Padovan 
34770a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
34780a708f8fSGustavo F. Padovan 
34790a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
34800a708f8fSGustavo F. Padovan 		u8 buf[8];
34810a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
34820a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
34830a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34840a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
34850a708f8fSGustavo F. Padovan 		if (!disable_ertm)
34860a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
34870a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3488a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
34896327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
34906327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3491a5fd6f30SAndrei Emeltchenko 
34920a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
34930a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34940a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
34950a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
34960a708f8fSGustavo F. Padovan 		u8 buf[12];
34970a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
349850a147cdSMat Martineau 
349950a147cdSMat Martineau 		if (enable_hs)
350050a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
350150a147cdSMat Martineau 		else
350250a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
350350a147cdSMat Martineau 
35040a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
35050a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3506c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
35070a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
35080a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
35090a708f8fSGustavo F. Padovan 	} else {
35100a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
35110a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
35120a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
35130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
35140a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
35150a708f8fSGustavo F. Padovan 	}
35160a708f8fSGustavo F. Padovan 
35170a708f8fSGustavo F. Padovan 	return 0;
35180a708f8fSGustavo F. Padovan }
35190a708f8fSGustavo F. Padovan 
35200a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
35210a708f8fSGustavo F. Padovan {
35220a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
35230a708f8fSGustavo F. Padovan 	u16 type, result;
35240a708f8fSGustavo F. Padovan 
35250a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
35260a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
35270a708f8fSGustavo F. Padovan 
35280a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
35290a708f8fSGustavo F. Padovan 
3530e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3531e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3532e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3533e90165beSAndrei Emeltchenko 		return 0;
3534e90165beSAndrei Emeltchenko 
353517cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
35360a708f8fSGustavo F. Padovan 
35370a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
35380a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35390a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
35400a708f8fSGustavo F. Padovan 
35410a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
35420a708f8fSGustavo F. Padovan 
35430a708f8fSGustavo F. Padovan 		return 0;
35440a708f8fSGustavo F. Padovan 	}
35450a708f8fSGustavo F. Padovan 
3546978c93b9SAndrei Emeltchenko 	switch (type) {
3547978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
35480a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
35490a708f8fSGustavo F. Padovan 
35500a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
35510a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
35520a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
35530a708f8fSGustavo F. Padovan 
35540a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
35550a708f8fSGustavo F. Padovan 
35560a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
35570a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
35580a708f8fSGustavo F. Padovan 		} else {
35590a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35600a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
35610a708f8fSGustavo F. Padovan 
35620a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
35630a708f8fSGustavo F. Padovan 		}
3564978c93b9SAndrei Emeltchenko 		break;
3565978c93b9SAndrei Emeltchenko 
3566978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3567978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
35680a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35690a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
35700a708f8fSGustavo F. Padovan 
35710a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3572978c93b9SAndrei Emeltchenko 		break;
35730a708f8fSGustavo F. Padovan 	}
35740a708f8fSGustavo F. Padovan 
35750a708f8fSGustavo F. Padovan 	return 0;
35760a708f8fSGustavo F. Padovan }
35770a708f8fSGustavo F. Padovan 
3578f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3579f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3580f94ff6ffSMat Martineau 					void *data)
3581f94ff6ffSMat Martineau {
3582f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3583f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3584f94ff6ffSMat Martineau 	u16 psm, scid;
3585f94ff6ffSMat Martineau 
3586f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3587f94ff6ffSMat Martineau 		return -EPROTO;
3588f94ff6ffSMat Martineau 
3589f94ff6ffSMat Martineau 	if (!enable_hs)
3590f94ff6ffSMat Martineau 		return -EINVAL;
3591f94ff6ffSMat Martineau 
3592f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3593f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3594f94ff6ffSMat Martineau 
3595f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3596f94ff6ffSMat Martineau 
3597f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3598f94ff6ffSMat Martineau 	rsp.dcid = 0;
3599f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
36008ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
36018ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3602f94ff6ffSMat Martineau 
3603f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3604f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3605f94ff6ffSMat Martineau 
3606f94ff6ffSMat Martineau 	return 0;
3607f94ff6ffSMat Martineau }
3608f94ff6ffSMat Martineau 
3609f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3610f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3611f94ff6ffSMat Martineau {
3612f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3613f94ff6ffSMat Martineau 
3614f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3615f94ff6ffSMat Martineau }
3616f94ff6ffSMat Martineau 
36178d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
36188d5a04a1SMat Martineau 							u16 icid, u16 result)
36198d5a04a1SMat Martineau {
36208d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
36218d5a04a1SMat Martineau 
36228d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36238d5a04a1SMat Martineau 
36248d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
36258d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
36268d5a04a1SMat Martineau 
36278d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
36288d5a04a1SMat Martineau }
36298d5a04a1SMat Martineau 
36308d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
36318d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
36328d5a04a1SMat Martineau {
36338d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
36348d5a04a1SMat Martineau 	u8 ident;
36358d5a04a1SMat Martineau 
36368d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36378d5a04a1SMat Martineau 
36388d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
36398d5a04a1SMat Martineau 	if (chan)
36408d5a04a1SMat Martineau 		chan->ident = ident;
36418d5a04a1SMat Martineau 
36428d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
36438d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
36448d5a04a1SMat Martineau 
36458d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
36468d5a04a1SMat Martineau }
36478d5a04a1SMat Martineau 
36488d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
36498d5a04a1SMat Martineau 								u16 icid)
36508d5a04a1SMat Martineau {
36518d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
36528d5a04a1SMat Martineau 
36538d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
36548d5a04a1SMat Martineau 
36558d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
36568d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
36578d5a04a1SMat Martineau }
36588d5a04a1SMat Martineau 
36598d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
36608d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36618d5a04a1SMat Martineau {
36628d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
36638d5a04a1SMat Martineau 	u16 icid = 0;
36648d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
36658d5a04a1SMat Martineau 
36668d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
36678d5a04a1SMat Martineau 		return -EPROTO;
36688d5a04a1SMat Martineau 
36698d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
36708d5a04a1SMat Martineau 
36718d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
36728d5a04a1SMat Martineau 
36738d5a04a1SMat Martineau 	if (!enable_hs)
36748d5a04a1SMat Martineau 		return -EINVAL;
36758d5a04a1SMat Martineau 
36768d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
36778d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
36788d5a04a1SMat Martineau 
36798d5a04a1SMat Martineau 	return 0;
36808d5a04a1SMat Martineau }
36818d5a04a1SMat Martineau 
36828d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
36838d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36848d5a04a1SMat Martineau {
36858d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
36868d5a04a1SMat Martineau 	u16 icid, result;
36878d5a04a1SMat Martineau 
36888d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36898d5a04a1SMat Martineau 		return -EPROTO;
36908d5a04a1SMat Martineau 
36918d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36928d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
36938d5a04a1SMat Martineau 
36948d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36958d5a04a1SMat Martineau 
36968d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
36978d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
36988d5a04a1SMat Martineau 
36998d5a04a1SMat Martineau 	return 0;
37008d5a04a1SMat Martineau }
37018d5a04a1SMat Martineau 
37028d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
37038d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
37048d5a04a1SMat Martineau {
37058d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
37068d5a04a1SMat Martineau 	u16 icid, result;
37078d5a04a1SMat Martineau 
37088d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
37098d5a04a1SMat Martineau 		return -EPROTO;
37108d5a04a1SMat Martineau 
37118d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
37128d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
37138d5a04a1SMat Martineau 
37148d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
37158d5a04a1SMat Martineau 
37168d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
37178d5a04a1SMat Martineau 
37188d5a04a1SMat Martineau 	return 0;
37198d5a04a1SMat Martineau }
37208d5a04a1SMat Martineau 
37218d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
37228d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
37238d5a04a1SMat Martineau {
37248d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
37258d5a04a1SMat Martineau 	u16 icid;
37268d5a04a1SMat Martineau 
37278d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
37288d5a04a1SMat Martineau 		return -EPROTO;
37298d5a04a1SMat Martineau 
37308d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
37318d5a04a1SMat Martineau 
37328d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
37338d5a04a1SMat Martineau 
37348d5a04a1SMat Martineau 	return 0;
37358d5a04a1SMat Martineau }
37368d5a04a1SMat Martineau 
3737e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3738de73115aSClaudio Takahasi 							u16 to_multiplier)
3739de73115aSClaudio Takahasi {
3740de73115aSClaudio Takahasi 	u16 max_latency;
3741de73115aSClaudio Takahasi 
3742de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3743de73115aSClaudio Takahasi 		return -EINVAL;
3744de73115aSClaudio Takahasi 
3745de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3746de73115aSClaudio Takahasi 		return -EINVAL;
3747de73115aSClaudio Takahasi 
3748de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3749de73115aSClaudio Takahasi 		return -EINVAL;
3750de73115aSClaudio Takahasi 
3751de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3752de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3753de73115aSClaudio Takahasi 		return -EINVAL;
3754de73115aSClaudio Takahasi 
3755de73115aSClaudio Takahasi 	return 0;
3756de73115aSClaudio Takahasi }
3757de73115aSClaudio Takahasi 
3758de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3759de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3760de73115aSClaudio Takahasi {
3761de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3762de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3763de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3764de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
37652ce603ebSClaudio Takahasi 	int err;
3766de73115aSClaudio Takahasi 
3767de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3768de73115aSClaudio Takahasi 		return -EINVAL;
3769de73115aSClaudio Takahasi 
3770de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3771de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3772de73115aSClaudio Takahasi 		return -EPROTO;
3773de73115aSClaudio Takahasi 
3774de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
3775de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
3776de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
3777de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
3778de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
3779de73115aSClaudio Takahasi 
3780de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3781de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
3782de73115aSClaudio Takahasi 
3783de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
37842ce603ebSClaudio Takahasi 
37852ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
37862ce603ebSClaudio Takahasi 	if (err)
3787de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3788de73115aSClaudio Takahasi 	else
3789de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3790de73115aSClaudio Takahasi 
3791de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3792de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
3793de73115aSClaudio Takahasi 
37942ce603ebSClaudio Takahasi 	if (!err)
37952ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
37962ce603ebSClaudio Takahasi 
3797de73115aSClaudio Takahasi 	return 0;
3798de73115aSClaudio Takahasi }
3799de73115aSClaudio Takahasi 
38003300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
38013300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
38023300d9a9SClaudio Takahasi {
38033300d9a9SClaudio Takahasi 	int err = 0;
38043300d9a9SClaudio Takahasi 
38053300d9a9SClaudio Takahasi 	switch (cmd->code) {
38063300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38073300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
38083300d9a9SClaudio Takahasi 		break;
38093300d9a9SClaudio Takahasi 
38103300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
38113300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
38123300d9a9SClaudio Takahasi 		break;
38133300d9a9SClaudio Takahasi 
38143300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
38153300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
38163300d9a9SClaudio Takahasi 		break;
38173300d9a9SClaudio Takahasi 
38183300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
38193300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
38203300d9a9SClaudio Takahasi 		break;
38213300d9a9SClaudio Takahasi 
38223300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
38233300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
38243300d9a9SClaudio Takahasi 		break;
38253300d9a9SClaudio Takahasi 
38263300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
38273300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
38283300d9a9SClaudio Takahasi 		break;
38293300d9a9SClaudio Takahasi 
38303300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
38313300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
38323300d9a9SClaudio Takahasi 		break;
38333300d9a9SClaudio Takahasi 
38343300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
38353300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
38363300d9a9SClaudio Takahasi 		break;
38373300d9a9SClaudio Takahasi 
38383300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
38393300d9a9SClaudio Takahasi 		break;
38403300d9a9SClaudio Takahasi 
38413300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
38423300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
38433300d9a9SClaudio Takahasi 		break;
38443300d9a9SClaudio Takahasi 
38453300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
38463300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
38473300d9a9SClaudio Takahasi 		break;
38483300d9a9SClaudio Takahasi 
3849f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
3850f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3851f94ff6ffSMat Martineau 		break;
3852f94ff6ffSMat Martineau 
3853f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
3854f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
3855f94ff6ffSMat Martineau 		break;
3856f94ff6ffSMat Martineau 
38578d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
38588d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
38598d5a04a1SMat Martineau 		break;
38608d5a04a1SMat Martineau 
38618d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
38628d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
38638d5a04a1SMat Martineau 		break;
38648d5a04a1SMat Martineau 
38658d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
38668d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
38678d5a04a1SMat Martineau 		break;
38688d5a04a1SMat Martineau 
38698d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
38708d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
38718d5a04a1SMat Martineau 		break;
38728d5a04a1SMat Martineau 
38733300d9a9SClaudio Takahasi 	default:
38743300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
38753300d9a9SClaudio Takahasi 		err = -EINVAL;
38763300d9a9SClaudio Takahasi 		break;
38773300d9a9SClaudio Takahasi 	}
38783300d9a9SClaudio Takahasi 
38793300d9a9SClaudio Takahasi 	return err;
38803300d9a9SClaudio Takahasi }
38813300d9a9SClaudio Takahasi 
38823300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
38833300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
38843300d9a9SClaudio Takahasi {
38853300d9a9SClaudio Takahasi 	switch (cmd->code) {
38863300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38873300d9a9SClaudio Takahasi 		return 0;
38883300d9a9SClaudio Takahasi 
38893300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
3890de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
38913300d9a9SClaudio Takahasi 
38923300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
38933300d9a9SClaudio Takahasi 		return 0;
38943300d9a9SClaudio Takahasi 
38953300d9a9SClaudio Takahasi 	default:
38963300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
38973300d9a9SClaudio Takahasi 		return -EINVAL;
38983300d9a9SClaudio Takahasi 	}
38993300d9a9SClaudio Takahasi }
39003300d9a9SClaudio Takahasi 
39013300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
39023300d9a9SClaudio Takahasi 							struct sk_buff *skb)
39030a708f8fSGustavo F. Padovan {
39040a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
39050a708f8fSGustavo F. Padovan 	int len = skb->len;
39060a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
39073300d9a9SClaudio Takahasi 	int err;
39080a708f8fSGustavo F. Padovan 
39090a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
39100a708f8fSGustavo F. Padovan 
39110a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
39120a708f8fSGustavo F. Padovan 		u16 cmd_len;
39130a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
39140a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
39150a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
39160a708f8fSGustavo F. Padovan 
39170a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
39180a708f8fSGustavo F. Padovan 
39190a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
39200a708f8fSGustavo F. Padovan 
39210a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
39220a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
39230a708f8fSGustavo F. Padovan 			break;
39240a708f8fSGustavo F. Padovan 		}
39250a708f8fSGustavo F. Padovan 
39263300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
39273300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
39283300d9a9SClaudio Takahasi 		else
39293300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
39300a708f8fSGustavo F. Padovan 
39310a708f8fSGustavo F. Padovan 		if (err) {
3932e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
39332c6d1a2eSGustavo F. Padovan 
39342c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
39350a708f8fSGustavo F. Padovan 
39360a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
3937e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
39380a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
39390a708f8fSGustavo F. Padovan 		}
39400a708f8fSGustavo F. Padovan 
39410a708f8fSGustavo F. Padovan 		data += cmd_len;
39420a708f8fSGustavo F. Padovan 		len  -= cmd_len;
39430a708f8fSGustavo F. Padovan 	}
39440a708f8fSGustavo F. Padovan 
39450a708f8fSGustavo F. Padovan 	kfree_skb(skb);
39460a708f8fSGustavo F. Padovan }
39470a708f8fSGustavo F. Padovan 
394847d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
39490a708f8fSGustavo F. Padovan {
39500a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
3951e4ca6d98SAndrei Emeltchenko 	int hdr_size;
3952e4ca6d98SAndrei Emeltchenko 
3953e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3954e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
3955e4ca6d98SAndrei Emeltchenko 	else
3956e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
39570a708f8fSGustavo F. Padovan 
395847d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
395903a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
39600a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
39610a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
39620a708f8fSGustavo F. Padovan 
39630a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
39640a708f8fSGustavo F. Padovan 			return -EBADMSG;
39650a708f8fSGustavo F. Padovan 	}
39660a708f8fSGustavo F. Padovan 	return 0;
39670a708f8fSGustavo F. Padovan }
39680a708f8fSGustavo F. Padovan 
3969525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
39700a708f8fSGustavo F. Padovan {
397188843ab0SAndrei Emeltchenko 	u32 control = 0;
39720a708f8fSGustavo F. Padovan 
39736a026610SGustavo F. Padovan 	chan->frames_sent = 0;
39740a708f8fSGustavo F. Padovan 
39750b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
39760a708f8fSGustavo F. Padovan 
3977e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3978ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
3979525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
3980e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
39810a708f8fSGustavo F. Padovan 	}
39820a708f8fSGustavo F. Padovan 
3983e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
3984525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
39850a708f8fSGustavo F. Padovan 
3986525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
39870a708f8fSGustavo F. Padovan 
3988e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
39896a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
3990ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3991525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
39920a708f8fSGustavo F. Padovan 	}
39930a708f8fSGustavo F. Padovan }
39940a708f8fSGustavo F. Padovan 
3995fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
39960a708f8fSGustavo F. Padovan {
39970a708f8fSGustavo F. Padovan 	struct sk_buff *next_skb;
39980a708f8fSGustavo F. Padovan 	int tx_seq_offset, next_tx_seq_offset;
39990a708f8fSGustavo F. Padovan 
40003ce3514fSMat Martineau 	bt_cb(skb)->control.txseq = tx_seq;
40013ce3514fSMat Martineau 	bt_cb(skb)->control.sar = sar;
40020a708f8fSGustavo F. Padovan 
4003f1c6775bSGustavo F. Padovan 	next_skb = skb_peek(&chan->srej_q);
40040a708f8fSGustavo F. Padovan 
4005836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
40060a708f8fSGustavo F. Padovan 
4007039d9572SSzymon Janc 	while (next_skb) {
40083ce3514fSMat Martineau 		if (bt_cb(next_skb)->control.txseq == tx_seq)
40090a708f8fSGustavo F. Padovan 			return -EINVAL;
40100a708f8fSGustavo F. Padovan 
4011836be934SAndrei Emeltchenko 		next_tx_seq_offset = __seq_offset(chan,
40123ce3514fSMat Martineau 			bt_cb(next_skb)->control.txseq, chan->buffer_seq);
40130a708f8fSGustavo F. Padovan 
40140a708f8fSGustavo F. Padovan 		if (next_tx_seq_offset > tx_seq_offset) {
4015f1c6775bSGustavo F. Padovan 			__skb_queue_before(&chan->srej_q, next_skb, skb);
40160a708f8fSGustavo F. Padovan 			return 0;
40170a708f8fSGustavo F. Padovan 		}
40180a708f8fSGustavo F. Padovan 
4019f1c6775bSGustavo F. Padovan 		if (skb_queue_is_last(&chan->srej_q, next_skb))
4020039d9572SSzymon Janc 			next_skb = NULL;
4021039d9572SSzymon Janc 		else
4022039d9572SSzymon Janc 			next_skb = skb_queue_next(&chan->srej_q, next_skb);
4023039d9572SSzymon Janc 	}
40240a708f8fSGustavo F. Padovan 
4025f1c6775bSGustavo F. Padovan 	__skb_queue_tail(&chan->srej_q, skb);
40260a708f8fSGustavo F. Padovan 
40270a708f8fSGustavo F. Padovan 	return 0;
40280a708f8fSGustavo F. Padovan }
40290a708f8fSGustavo F. Padovan 
403084084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
403184084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
40320a708f8fSGustavo F. Padovan {
403384084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
403484084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
403584084a31SMat Martineau 	 */
403684084a31SMat Martineau 	if (!skb_has_frag_list(skb))
403784084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
403884084a31SMat Martineau 
403984084a31SMat Martineau 	new_frag->next = NULL;
404084084a31SMat Martineau 
404184084a31SMat Martineau 	(*last_frag)->next = new_frag;
404284084a31SMat Martineau 	*last_frag = new_frag;
404384084a31SMat Martineau 
404484084a31SMat Martineau 	skb->len += new_frag->len;
404584084a31SMat Martineau 	skb->data_len += new_frag->len;
404684084a31SMat Martineau 	skb->truesize += new_frag->truesize;
404784084a31SMat Martineau }
404884084a31SMat Martineau 
404988843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
405084084a31SMat Martineau {
405184084a31SMat Martineau 	int err = -EINVAL;
40520a708f8fSGustavo F. Padovan 
40537e0ef6eeSAndrei Emeltchenko 	switch (__get_ctrl_sar(chan, control)) {
40547e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
405584084a31SMat Martineau 		if (chan->sdu)
405684084a31SMat Martineau 			break;
40570a708f8fSGustavo F. Padovan 
405884084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
405984084a31SMat Martineau 		break;
40600a708f8fSGustavo F. Padovan 
40617e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
406284084a31SMat Martineau 		if (chan->sdu)
406384084a31SMat Martineau 			break;
40640a708f8fSGustavo F. Padovan 
40656f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
406603a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
40670a708f8fSGustavo F. Padovan 
406884084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
406984084a31SMat Martineau 			err = -EMSGSIZE;
407084084a31SMat Martineau 			break;
407184084a31SMat Martineau 		}
40720a708f8fSGustavo F. Padovan 
407384084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
407484084a31SMat Martineau 			break;
407584084a31SMat Martineau 
407684084a31SMat Martineau 		chan->sdu = skb;
407784084a31SMat Martineau 		chan->sdu_last_frag = skb;
407884084a31SMat Martineau 
407984084a31SMat Martineau 		skb = NULL;
408084084a31SMat Martineau 		err = 0;
40810a708f8fSGustavo F. Padovan 		break;
40820a708f8fSGustavo F. Padovan 
40837e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
40846f61fd47SGustavo F. Padovan 		if (!chan->sdu)
408584084a31SMat Martineau 			break;
40860a708f8fSGustavo F. Padovan 
408784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
408884084a31SMat Martineau 				&chan->sdu_last_frag);
408984084a31SMat Martineau 		skb = NULL;
40900a708f8fSGustavo F. Padovan 
409184084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
409284084a31SMat Martineau 			break;
40930a708f8fSGustavo F. Padovan 
409484084a31SMat Martineau 		err = 0;
40950a708f8fSGustavo F. Padovan 		break;
40960a708f8fSGustavo F. Padovan 
40977e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
40986f61fd47SGustavo F. Padovan 		if (!chan->sdu)
409984084a31SMat Martineau 			break;
41000a708f8fSGustavo F. Padovan 
410184084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
410284084a31SMat Martineau 				&chan->sdu_last_frag);
410384084a31SMat Martineau 		skb = NULL;
41040a708f8fSGustavo F. Padovan 
410584084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
410684084a31SMat Martineau 			break;
41070a708f8fSGustavo F. Padovan 
410884084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
41090a708f8fSGustavo F. Padovan 
411084084a31SMat Martineau 		if (!err) {
411184084a31SMat Martineau 			/* Reassembly complete */
411284084a31SMat Martineau 			chan->sdu = NULL;
411384084a31SMat Martineau 			chan->sdu_last_frag = NULL;
411484084a31SMat Martineau 			chan->sdu_len = 0;
41150a708f8fSGustavo F. Padovan 		}
41160a708f8fSGustavo F. Padovan 		break;
41170a708f8fSGustavo F. Padovan 	}
41180a708f8fSGustavo F. Padovan 
411984084a31SMat Martineau 	if (err) {
41200a708f8fSGustavo F. Padovan 		kfree_skb(skb);
41216f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
41226f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
412384084a31SMat Martineau 		chan->sdu_last_frag = NULL;
412484084a31SMat Martineau 		chan->sdu_len = 0;
412584084a31SMat Martineau 	}
41260a708f8fSGustavo F. Padovan 
412784084a31SMat Martineau 	return err;
41280a708f8fSGustavo F. Padovan }
41290a708f8fSGustavo F. Padovan 
413026f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
41310a708f8fSGustavo F. Padovan {
413226f880d2SMat Martineau 	BT_DBG("chan %p, Enter local busy", chan);
413326f880d2SMat Martineau 
413426f880d2SMat Martineau 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
41353c588192SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
413626f880d2SMat Martineau 
413777f918bcSSzymon Janc 	__set_ack_timer(chan);
41380a708f8fSGustavo F. Padovan }
41390a708f8fSGustavo F. Padovan 
414026f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
414126f880d2SMat Martineau {
414288843ab0SAndrei Emeltchenko 	u32 control;
41430a708f8fSGustavo F. Padovan 
4144e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
41450a708f8fSGustavo F. Padovan 		goto done;
41460a708f8fSGustavo F. Padovan 
41470b209faeSAndrei Emeltchenko 	control = __set_reqseq(chan, chan->buffer_seq);
4148e3781735SAndrei Emeltchenko 	control |= __set_ctrl_poll(chan);
4149ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4150525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
41516a026610SGustavo F. Padovan 	chan->retry_count = 1;
41520a708f8fSGustavo F. Padovan 
41531a09bcb9SGustavo F. Padovan 	__clear_retrans_timer(chan);
41541a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
41550a708f8fSGustavo F. Padovan 
4156e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
41570a708f8fSGustavo F. Padovan 
41580a708f8fSGustavo F. Padovan done:
4159e2ab4353SGustavo F. Padovan 	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4160e2ab4353SGustavo F. Padovan 	clear_bit(CONN_RNR_SENT, &chan->conn_state);
41610a708f8fSGustavo F. Padovan 
416249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, Exit local busy", chan);
41630a708f8fSGustavo F. Padovan }
41640a708f8fSGustavo F. Padovan 
4165e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
41660a708f8fSGustavo F. Padovan {
4167e328140fSMat Martineau 	if (chan->mode == L2CAP_MODE_ERTM) {
4168e328140fSMat Martineau 		if (busy)
416926f880d2SMat Martineau 			l2cap_ertm_enter_local_busy(chan);
4170e328140fSMat Martineau 		else
4171e328140fSMat Martineau 			l2cap_ertm_exit_local_busy(chan);
41720a708f8fSGustavo F. Padovan 	}
41730a708f8fSGustavo F. Padovan }
41740a708f8fSGustavo F. Padovan 
4175fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
41760a708f8fSGustavo F. Padovan {
41770a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
417888843ab0SAndrei Emeltchenko 	u32 control;
41790a708f8fSGustavo F. Padovan 
4180e328140fSMat Martineau 	while ((skb = skb_peek(&chan->srej_q)) &&
4181e328140fSMat Martineau 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4182e328140fSMat Martineau 		int err;
4183e328140fSMat Martineau 
41843ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq != tx_seq)
41850a708f8fSGustavo F. Padovan 			break;
41860a708f8fSGustavo F. Padovan 
4187f1c6775bSGustavo F. Padovan 		skb = skb_dequeue(&chan->srej_q);
41883ce3514fSMat Martineau 		control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
418984084a31SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, control);
4190e328140fSMat Martineau 
4191e328140fSMat Martineau 		if (err < 0) {
4192e328140fSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4193e328140fSMat Martineau 			break;
4194e328140fSMat Martineau 		}
4195e328140fSMat Martineau 
4196836be934SAndrei Emeltchenko 		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4197836be934SAndrei Emeltchenko 		tx_seq = __next_seq(chan, tx_seq);
41980a708f8fSGustavo F. Padovan 	}
41990a708f8fSGustavo F. Padovan }
42000a708f8fSGustavo F. Padovan 
4201fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
42020a708f8fSGustavo F. Padovan {
42030a708f8fSGustavo F. Padovan 	struct srej_list *l, *tmp;
420488843ab0SAndrei Emeltchenko 	u32 control;
42050a708f8fSGustavo F. Padovan 
420639d5a3eeSGustavo F. Padovan 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
42070a708f8fSGustavo F. Padovan 		if (l->tx_seq == tx_seq) {
42080a708f8fSGustavo F. Padovan 			list_del(&l->list);
42090a708f8fSGustavo F. Padovan 			kfree(l);
42100a708f8fSGustavo F. Padovan 			return;
42110a708f8fSGustavo F. Padovan 		}
4212ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
42130b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, l->tx_seq);
4214525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
42150a708f8fSGustavo F. Padovan 		list_del(&l->list);
421639d5a3eeSGustavo F. Padovan 		list_add_tail(&l->list, &chan->srej_l);
42170a708f8fSGustavo F. Padovan 	}
42180a708f8fSGustavo F. Padovan }
42190a708f8fSGustavo F. Padovan 
4220aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
42210a708f8fSGustavo F. Padovan {
42220a708f8fSGustavo F. Padovan 	struct srej_list *new;
422388843ab0SAndrei Emeltchenko 	u32 control;
42240a708f8fSGustavo F. Padovan 
422542e5c802SGustavo F. Padovan 	while (tx_seq != chan->expected_tx_seq) {
4226ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
42270b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->expected_tx_seq);
42283c588192SMat Martineau 		l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
4229525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
42300a708f8fSGustavo F. Padovan 
42310a708f8fSGustavo F. Padovan 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
4232aef89f21SSzymon Janc 		if (!new)
4233aef89f21SSzymon Janc 			return -ENOMEM;
4234aef89f21SSzymon Janc 
423542e5c802SGustavo F. Padovan 		new->tx_seq = chan->expected_tx_seq;
4236836be934SAndrei Emeltchenko 
4237836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4238836be934SAndrei Emeltchenko 
423939d5a3eeSGustavo F. Padovan 		list_add_tail(&new->list, &chan->srej_l);
42400a708f8fSGustavo F. Padovan 	}
4241836be934SAndrei Emeltchenko 
4242836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4243aef89f21SSzymon Janc 
4244aef89f21SSzymon Janc 	return 0;
42450a708f8fSGustavo F. Padovan }
42460a708f8fSGustavo F. Padovan 
424788843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
42480a708f8fSGustavo F. Padovan {
4249fb45de7dSAndrei Emeltchenko 	u16 tx_seq = __get_txseq(chan, rx_control);
42500b209faeSAndrei Emeltchenko 	u16 req_seq = __get_reqseq(chan, rx_control);
42517e0ef6eeSAndrei Emeltchenko 	u8 sar = __get_ctrl_sar(chan, rx_control);
42520a708f8fSGustavo F. Padovan 	int tx_seq_offset, expected_tx_seq_offset;
425347d1ec61SGustavo F. Padovan 	int num_to_ack = (chan->tx_win/6) + 1;
42540a708f8fSGustavo F. Padovan 	int err = 0;
42550a708f8fSGustavo F. Padovan 
425688843ab0SAndrei Emeltchenko 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
4257525cd185SGustavo F. Padovan 							tx_seq, rx_control);
42580a708f8fSGustavo F. Padovan 
425903f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4260e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
42611a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
42626a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
42631a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4264e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
42650a708f8fSGustavo F. Padovan 	}
42660a708f8fSGustavo F. Padovan 
426742e5c802SGustavo F. Padovan 	chan->expected_ack_seq = req_seq;
426842e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
42690a708f8fSGustavo F. Padovan 
4270836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
42710a708f8fSGustavo F. Padovan 
42720a708f8fSGustavo F. Padovan 	/* invalid tx_seq */
427347d1ec61SGustavo F. Padovan 	if (tx_seq_offset >= chan->tx_win) {
42748c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42750a708f8fSGustavo F. Padovan 		goto drop;
42760a708f8fSGustavo F. Padovan 	}
42770a708f8fSGustavo F. Padovan 
427877f918bcSSzymon Janc 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
427977f918bcSSzymon Janc 		if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
428077f918bcSSzymon Janc 			l2cap_send_ack(chan);
42810a708f8fSGustavo F. Padovan 		goto drop;
428277f918bcSSzymon Janc 	}
42830a708f8fSGustavo F. Padovan 
428402f1b641SMat Martineau 	if (tx_seq == chan->expected_tx_seq)
428502f1b641SMat Martineau 		goto expected;
428602f1b641SMat Martineau 
4287e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
42880a708f8fSGustavo F. Padovan 		struct srej_list *first;
42890a708f8fSGustavo F. Padovan 
429039d5a3eeSGustavo F. Padovan 		first = list_first_entry(&chan->srej_l,
42910a708f8fSGustavo F. Padovan 				struct srej_list, list);
42920a708f8fSGustavo F. Padovan 		if (tx_seq == first->tx_seq) {
429342e5c802SGustavo F. Padovan 			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
4294525cd185SGustavo F. Padovan 			l2cap_check_srej_gap(chan, tx_seq);
42950a708f8fSGustavo F. Padovan 
42960a708f8fSGustavo F. Padovan 			list_del(&first->list);
42970a708f8fSGustavo F. Padovan 			kfree(first);
42980a708f8fSGustavo F. Padovan 
429939d5a3eeSGustavo F. Padovan 			if (list_empty(&chan->srej_l)) {
430042e5c802SGustavo F. Padovan 				chan->buffer_seq = chan->buffer_seq_srej;
4301e2ab4353SGustavo F. Padovan 				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
4302525cd185SGustavo F. Padovan 				l2cap_send_ack(chan);
430349208c9cSGustavo F. Padovan 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
43040a708f8fSGustavo F. Padovan 			}
43050a708f8fSGustavo F. Padovan 		} else {
43060a708f8fSGustavo F. Padovan 			struct srej_list *l;
43070a708f8fSGustavo F. Padovan 
43080a708f8fSGustavo F. Padovan 			/* duplicated tx_seq */
430942e5c802SGustavo F. Padovan 			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
43100a708f8fSGustavo F. Padovan 				goto drop;
43110a708f8fSGustavo F. Padovan 
431239d5a3eeSGustavo F. Padovan 			list_for_each_entry(l, &chan->srej_l, list) {
43130a708f8fSGustavo F. Padovan 				if (l->tx_seq == tx_seq) {
4314525cd185SGustavo F. Padovan 					l2cap_resend_srejframe(chan, tx_seq);
43150a708f8fSGustavo F. Padovan 					return 0;
43160a708f8fSGustavo F. Padovan 				}
43170a708f8fSGustavo F. Padovan 			}
4318aef89f21SSzymon Janc 
4319aef89f21SSzymon Janc 			err = l2cap_send_srejframe(chan, tx_seq);
4320aef89f21SSzymon Janc 			if (err < 0) {
4321aef89f21SSzymon Janc 				l2cap_send_disconn_req(chan->conn, chan, -err);
4322aef89f21SSzymon Janc 				return err;
4323aef89f21SSzymon Janc 			}
43240a708f8fSGustavo F. Padovan 		}
43250a708f8fSGustavo F. Padovan 	} else {
4326836be934SAndrei Emeltchenko 		expected_tx_seq_offset = __seq_offset(chan,
4327836be934SAndrei Emeltchenko 				chan->expected_tx_seq, chan->buffer_seq);
43280a708f8fSGustavo F. Padovan 
43290a708f8fSGustavo F. Padovan 		/* duplicated tx_seq */
43300a708f8fSGustavo F. Padovan 		if (tx_seq_offset < expected_tx_seq_offset)
43310a708f8fSGustavo F. Padovan 			goto drop;
43320a708f8fSGustavo F. Padovan 
4333e2ab4353SGustavo F. Padovan 		set_bit(CONN_SREJ_SENT, &chan->conn_state);
43340a708f8fSGustavo F. Padovan 
433549208c9cSGustavo F. Padovan 		BT_DBG("chan %p, Enter SREJ", chan);
43360a708f8fSGustavo F. Padovan 
433739d5a3eeSGustavo F. Padovan 		INIT_LIST_HEAD(&chan->srej_l);
433842e5c802SGustavo F. Padovan 		chan->buffer_seq_srej = chan->buffer_seq;
43390a708f8fSGustavo F. Padovan 
4340f1c6775bSGustavo F. Padovan 		__skb_queue_head_init(&chan->srej_q);
434142e5c802SGustavo F. Padovan 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
43420a708f8fSGustavo F. Padovan 
43430ef3ef0fSSzymon Janc 		/* Set P-bit only if there are some I-frames to ack. */
43440ef3ef0fSSzymon Janc 		if (__clear_ack_timer(chan))
4345e2ab4353SGustavo F. Padovan 			set_bit(CONN_SEND_PBIT, &chan->conn_state);
43460a708f8fSGustavo F. Padovan 
4347aef89f21SSzymon Janc 		err = l2cap_send_srejframe(chan, tx_seq);
4348aef89f21SSzymon Janc 		if (err < 0) {
4349aef89f21SSzymon Janc 			l2cap_send_disconn_req(chan->conn, chan, -err);
4350aef89f21SSzymon Janc 			return err;
4351aef89f21SSzymon Janc 		}
43520a708f8fSGustavo F. Padovan 	}
43530a708f8fSGustavo F. Padovan 	return 0;
43540a708f8fSGustavo F. Padovan 
43550a708f8fSGustavo F. Padovan expected:
4356836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
43570a708f8fSGustavo F. Padovan 
4358e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
43593ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = tx_seq;
43603ce3514fSMat Martineau 		bt_cb(skb)->control.sar = sar;
4361f1c6775bSGustavo F. Padovan 		__skb_queue_tail(&chan->srej_q, skb);
43620a708f8fSGustavo F. Padovan 		return 0;
43630a708f8fSGustavo F. Padovan 	}
43640a708f8fSGustavo F. Padovan 
436584084a31SMat Martineau 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
4366836be934SAndrei Emeltchenko 	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4367836be934SAndrei Emeltchenko 
4368e328140fSMat Martineau 	if (err < 0) {
4369e328140fSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4370e328140fSMat Martineau 		return err;
4371e328140fSMat Martineau 	}
43720a708f8fSGustavo F. Padovan 
437303f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4374e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4375525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43760a708f8fSGustavo F. Padovan 	}
43770a708f8fSGustavo F. Padovan 
43780a708f8fSGustavo F. Padovan 
43796a026610SGustavo F. Padovan 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
43806a026610SGustavo F. Padovan 	if (chan->num_acked == num_to_ack - 1)
4381525cd185SGustavo F. Padovan 		l2cap_send_ack(chan);
43824d611e4dSGustavo F. Padovan 	else
43834d611e4dSGustavo F. Padovan 		__set_ack_timer(chan);
43840a708f8fSGustavo F. Padovan 
43850a708f8fSGustavo F. Padovan 	return 0;
43860a708f8fSGustavo F. Padovan 
43870a708f8fSGustavo F. Padovan drop:
43880a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43890a708f8fSGustavo F. Padovan 	return 0;
43900a708f8fSGustavo F. Padovan }
43910a708f8fSGustavo F. Padovan 
439288843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
43930a708f8fSGustavo F. Padovan {
439488843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
43950b209faeSAndrei Emeltchenko 				__get_reqseq(chan, rx_control), rx_control);
43960a708f8fSGustavo F. Padovan 
43970b209faeSAndrei Emeltchenko 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
439842e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
43990a708f8fSGustavo F. Padovan 
4400e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4401e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4402e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4403e2ab4353SGustavo F. Padovan 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
44046a026610SGustavo F. Padovan 					(chan->unacked_frames > 0))
44051a09bcb9SGustavo F. Padovan 				__set_retrans_timer(chan);
44060a708f8fSGustavo F. Padovan 
4407e2ab4353SGustavo F. Padovan 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4408525cd185SGustavo F. Padovan 			l2cap_send_srejtail(chan);
44090a708f8fSGustavo F. Padovan 		} else {
4410525cd185SGustavo F. Padovan 			l2cap_send_i_or_rr_or_rnr(chan);
44110a708f8fSGustavo F. Padovan 		}
44120a708f8fSGustavo F. Padovan 
441303f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4414e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44150a708f8fSGustavo F. Padovan 
4416e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4417525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
44180a708f8fSGustavo F. Padovan 
44190a708f8fSGustavo F. Padovan 	} else {
4420e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
44216a026610SGustavo F. Padovan 				(chan->unacked_frames > 0))
44221a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
44230a708f8fSGustavo F. Padovan 
4424e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4425e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
4426525cd185SGustavo F. Padovan 			l2cap_send_ack(chan);
44270a708f8fSGustavo F. Padovan 		else
4428525cd185SGustavo F. Padovan 			l2cap_ertm_send(chan);
44290a708f8fSGustavo F. Padovan 	}
44300a708f8fSGustavo F. Padovan }
44310a708f8fSGustavo F. Padovan 
443288843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
44330a708f8fSGustavo F. Padovan {
44340b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44350a708f8fSGustavo F. Padovan 
443688843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44370a708f8fSGustavo F. Padovan 
4438e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44390a708f8fSGustavo F. Padovan 
444042e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
444142e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44420a708f8fSGustavo F. Padovan 
444303f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4444e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4445525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
44460a708f8fSGustavo F. Padovan 	} else {
4447525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
44480a708f8fSGustavo F. Padovan 
4449e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state))
4450e2ab4353SGustavo F. Padovan 			set_bit(CONN_REJ_ACT, &chan->conn_state);
44510a708f8fSGustavo F. Padovan 	}
44520a708f8fSGustavo F. Padovan }
445388843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
44540a708f8fSGustavo F. Padovan {
44550b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44560a708f8fSGustavo F. Padovan 
445788843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44580a708f8fSGustavo F. Padovan 
4459e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44600a708f8fSGustavo F. Padovan 
4461e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
446242e5c802SGustavo F. Padovan 		chan->expected_ack_seq = tx_seq;
446342e5c802SGustavo F. Padovan 		l2cap_drop_acked_frames(chan);
44640a708f8fSGustavo F. Padovan 
4465e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4466525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
44670a708f8fSGustavo F. Padovan 
4468525cd185SGustavo F. Padovan 		l2cap_ertm_send(chan);
44690a708f8fSGustavo F. Padovan 
4470e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44716a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4472e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44730a708f8fSGustavo F. Padovan 		}
447403f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4475e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
44766a026610SGustavo F. Padovan 				chan->srej_save_reqseq == tx_seq)
4477e2ab4353SGustavo F. Padovan 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
44780a708f8fSGustavo F. Padovan 		else
4479525cd185SGustavo F. Padovan 			l2cap_retransmit_one_frame(chan, tx_seq);
44800a708f8fSGustavo F. Padovan 	} else {
4481525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
4482e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44836a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4484e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44850a708f8fSGustavo F. Padovan 		}
44860a708f8fSGustavo F. Padovan 	}
44870a708f8fSGustavo F. Padovan }
44880a708f8fSGustavo F. Padovan 
448988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
44900a708f8fSGustavo F. Padovan {
44910b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44920a708f8fSGustavo F. Padovan 
449388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44940a708f8fSGustavo F. Padovan 
4495e2ab4353SGustavo F. Padovan 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
449642e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
449742e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44980a708f8fSGustavo F. Padovan 
4499e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control))
4500e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
45010a708f8fSGustavo F. Padovan 
4502e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
45031a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4504e3781735SAndrei Emeltchenko 		if (__is_ctrl_poll(chan, rx_control))
4505525cd185SGustavo F. Padovan 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
45060a708f8fSGustavo F. Padovan 		return;
45070a708f8fSGustavo F. Padovan 	}
45080a708f8fSGustavo F. Padovan 
4509e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4510525cd185SGustavo F. Padovan 		l2cap_send_srejtail(chan);
4511ab784b73SAndrei Emeltchenko 	} else {
4512ab784b73SAndrei Emeltchenko 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4513ab784b73SAndrei Emeltchenko 		l2cap_send_sframe(chan, rx_control);
4514ab784b73SAndrei Emeltchenko 	}
45150a708f8fSGustavo F. Padovan }
45160a708f8fSGustavo F. Padovan 
451788843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
45180a708f8fSGustavo F. Padovan {
451988843ab0SAndrei Emeltchenko 	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
45200a708f8fSGustavo F. Padovan 
452103f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4522e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
45231a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
45246a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
45251a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4526e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
45270a708f8fSGustavo F. Padovan 	}
45280a708f8fSGustavo F. Padovan 
4529ab784b73SAndrei Emeltchenko 	switch (__get_ctrl_super(chan, rx_control)) {
4530ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RR:
4531525cd185SGustavo F. Padovan 		l2cap_data_channel_rrframe(chan, rx_control);
45320a708f8fSGustavo F. Padovan 		break;
45330a708f8fSGustavo F. Padovan 
4534ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_REJ:
4535525cd185SGustavo F. Padovan 		l2cap_data_channel_rejframe(chan, rx_control);
45360a708f8fSGustavo F. Padovan 		break;
45370a708f8fSGustavo F. Padovan 
4538ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_SREJ:
4539525cd185SGustavo F. Padovan 		l2cap_data_channel_srejframe(chan, rx_control);
45400a708f8fSGustavo F. Padovan 		break;
45410a708f8fSGustavo F. Padovan 
4542ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RNR:
4543525cd185SGustavo F. Padovan 		l2cap_data_channel_rnrframe(chan, rx_control);
45440a708f8fSGustavo F. Padovan 		break;
45450a708f8fSGustavo F. Padovan 	}
45460a708f8fSGustavo F. Padovan 
45470a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45480a708f8fSGustavo F. Padovan 	return 0;
45490a708f8fSGustavo F. Padovan }
45500a708f8fSGustavo F. Padovan 
4551cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
45520a708f8fSGustavo F. Padovan {
455388843ab0SAndrei Emeltchenko 	u32 control;
45540b209faeSAndrei Emeltchenko 	u16 req_seq;
45550a708f8fSGustavo F. Padovan 	int len, next_tx_seq_offset, req_seq_offset;
45560a708f8fSGustavo F. Padovan 
4557b76bbd66SMat Martineau 	__unpack_control(chan, skb);
4558b76bbd66SMat Martineau 
455988843ab0SAndrei Emeltchenko 	control = __get_control(chan, skb->data);
456088843ab0SAndrei Emeltchenko 	skb_pull(skb, __ctrl_size(chan));
45610a708f8fSGustavo F. Padovan 	len = skb->len;
45620a708f8fSGustavo F. Padovan 
45630a708f8fSGustavo F. Padovan 	/*
45640a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
45650a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
45660a708f8fSGustavo F. Padovan 	 * procedures and ask retransmission.
45670a708f8fSGustavo F. Padovan 	 */
456847d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
45690a708f8fSGustavo F. Padovan 		goto drop;
45700a708f8fSGustavo F. Padovan 
4571793c2f1cSAndrei Emeltchenko 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
457203a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
45730a708f8fSGustavo F. Padovan 
457447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
457503a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
45760a708f8fSGustavo F. Padovan 
457747d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
45788c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45790a708f8fSGustavo F. Padovan 		goto drop;
45800a708f8fSGustavo F. Padovan 	}
45810a708f8fSGustavo F. Padovan 
45820b209faeSAndrei Emeltchenko 	req_seq = __get_reqseq(chan, control);
45830a708f8fSGustavo F. Padovan 
4584836be934SAndrei Emeltchenko 	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4585836be934SAndrei Emeltchenko 
4586836be934SAndrei Emeltchenko 	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4587836be934SAndrei Emeltchenko 						chan->expected_ack_seq);
45880a708f8fSGustavo F. Padovan 
45890a708f8fSGustavo F. Padovan 	/* check for invalid req-seq */
45900a708f8fSGustavo F. Padovan 	if (req_seq_offset > next_tx_seq_offset) {
45918c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45920a708f8fSGustavo F. Padovan 		goto drop;
45930a708f8fSGustavo F. Padovan 	}
45940a708f8fSGustavo F. Padovan 
4595793c2f1cSAndrei Emeltchenko 	if (!__is_sframe(chan, control)) {
45960a708f8fSGustavo F. Padovan 		if (len < 0) {
45978c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45980a708f8fSGustavo F. Padovan 			goto drop;
45990a708f8fSGustavo F. Padovan 		}
46000a708f8fSGustavo F. Padovan 
4601525cd185SGustavo F. Padovan 		l2cap_data_channel_iframe(chan, control, skb);
46020a708f8fSGustavo F. Padovan 	} else {
46030a708f8fSGustavo F. Padovan 		if (len != 0) {
46040a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
46058c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46060a708f8fSGustavo F. Padovan 			goto drop;
46070a708f8fSGustavo F. Padovan 		}
46080a708f8fSGustavo F. Padovan 
4609525cd185SGustavo F. Padovan 		l2cap_data_channel_sframe(chan, control, skb);
46100a708f8fSGustavo F. Padovan 	}
46110a708f8fSGustavo F. Padovan 
46120a708f8fSGustavo F. Padovan 	return 0;
46130a708f8fSGustavo F. Padovan 
46140a708f8fSGustavo F. Padovan drop:
46150a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46160a708f8fSGustavo F. Padovan 	return 0;
46170a708f8fSGustavo F. Padovan }
46180a708f8fSGustavo F. Padovan 
46190a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
46200a708f8fSGustavo F. Padovan {
462148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
462288843ab0SAndrei Emeltchenko 	u32 control;
4623fb45de7dSAndrei Emeltchenko 	u16 tx_seq;
46240a708f8fSGustavo F. Padovan 	int len;
46250a708f8fSGustavo F. Padovan 
4626baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
462748454079SGustavo F. Padovan 	if (!chan) {
46280a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
46296be36555SAndrei Emeltchenko 		/* Drop packet and return */
46303379013bSDan Carpenter 		kfree_skb(skb);
46316be36555SAndrei Emeltchenko 		return 0;
46320a708f8fSGustavo F. Padovan 	}
46330a708f8fSGustavo F. Padovan 
46346be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
46350a708f8fSGustavo F. Padovan 
463649208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
46370a708f8fSGustavo F. Padovan 
463889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
46390a708f8fSGustavo F. Padovan 		goto drop;
46400a708f8fSGustavo F. Padovan 
46410c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
46420a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
46430a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
46440a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
46450a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
46460a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
46470a708f8fSGustavo F. Padovan 
46480c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
46490a708f8fSGustavo F. Padovan 			goto drop;
46500a708f8fSGustavo F. Padovan 
465123070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
46520a708f8fSGustavo F. Padovan 			goto done;
46530a708f8fSGustavo F. Padovan 		break;
46540a708f8fSGustavo F. Padovan 
46550a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
46565ef8cb9eSAndrei Emeltchenko 		l2cap_ertm_data_rcv(chan, skb);
46570a708f8fSGustavo F. Padovan 
46580a708f8fSGustavo F. Padovan 		goto done;
46590a708f8fSGustavo F. Padovan 
46600a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
466188843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data);
466288843ab0SAndrei Emeltchenko 		skb_pull(skb, __ctrl_size(chan));
46630a708f8fSGustavo F. Padovan 		len = skb->len;
46640a708f8fSGustavo F. Padovan 
466547d1ec61SGustavo F. Padovan 		if (l2cap_check_fcs(chan, skb))
46660a708f8fSGustavo F. Padovan 			goto drop;
46670a708f8fSGustavo F. Padovan 
46687e0ef6eeSAndrei Emeltchenko 		if (__is_sar_start(chan, control))
466903a51213SAndrei Emeltchenko 			len -= L2CAP_SDULEN_SIZE;
46700a708f8fSGustavo F. Padovan 
467147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16)
467203a51213SAndrei Emeltchenko 			len -= L2CAP_FCS_SIZE;
46730a708f8fSGustavo F. Padovan 
4674793c2f1cSAndrei Emeltchenko 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
46750a708f8fSGustavo F. Padovan 			goto drop;
46760a708f8fSGustavo F. Padovan 
4677fb45de7dSAndrei Emeltchenko 		tx_seq = __get_txseq(chan, control);
46780a708f8fSGustavo F. Padovan 
467984084a31SMat Martineau 		if (chan->expected_tx_seq != tx_seq) {
468084084a31SMat Martineau 			/* Frame(s) missing - must discard partial SDU */
468184084a31SMat Martineau 			kfree_skb(chan->sdu);
468284084a31SMat Martineau 			chan->sdu = NULL;
468384084a31SMat Martineau 			chan->sdu_last_frag = NULL;
468484084a31SMat Martineau 			chan->sdu_len = 0;
468584084a31SMat Martineau 
468684084a31SMat Martineau 			/* TODO: Notify userland of missing data */
468784084a31SMat Martineau 		}
468884084a31SMat Martineau 
4689836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, tx_seq);
46900a708f8fSGustavo F. Padovan 
469184084a31SMat Martineau 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
469284084a31SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46930a708f8fSGustavo F. Padovan 
46940a708f8fSGustavo F. Padovan 		goto done;
46950a708f8fSGustavo F. Padovan 
46960a708f8fSGustavo F. Padovan 	default:
46970c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
46980a708f8fSGustavo F. Padovan 		break;
46990a708f8fSGustavo F. Padovan 	}
47000a708f8fSGustavo F. Padovan 
47010a708f8fSGustavo F. Padovan drop:
47020a708f8fSGustavo F. Padovan 	kfree_skb(skb);
47030a708f8fSGustavo F. Padovan 
47040a708f8fSGustavo F. Padovan done:
47056be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
47060a708f8fSGustavo F. Padovan 
47070a708f8fSGustavo F. Padovan 	return 0;
47080a708f8fSGustavo F. Padovan }
47090a708f8fSGustavo F. Padovan 
47100a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
47110a708f8fSGustavo F. Padovan {
471223691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
47130a708f8fSGustavo F. Padovan 
4714c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
471523691d75SGustavo F. Padovan 	if (!chan)
47160a708f8fSGustavo F. Padovan 		goto drop;
47170a708f8fSGustavo F. Padovan 
47185b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
47190a708f8fSGustavo F. Padovan 
472089bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
47210a708f8fSGustavo F. Padovan 		goto drop;
47220a708f8fSGustavo F. Padovan 
4723e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
47240a708f8fSGustavo F. Padovan 		goto drop;
47250a708f8fSGustavo F. Padovan 
472623070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
47275b4cedaaSAndrei Emeltchenko 		return 0;
47280a708f8fSGustavo F. Padovan 
47290a708f8fSGustavo F. Padovan drop:
47300a708f8fSGustavo F. Padovan 	kfree_skb(skb);
47310a708f8fSGustavo F. Padovan 
47320a708f8fSGustavo F. Padovan 	return 0;
47330a708f8fSGustavo F. Padovan }
47340a708f8fSGustavo F. Padovan 
4735d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4736d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
47379f69bda6SGustavo F. Padovan {
473823691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
47399f69bda6SGustavo F. Padovan 
4740c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
474123691d75SGustavo F. Padovan 	if (!chan)
47429f69bda6SGustavo F. Padovan 		goto drop;
47439f69bda6SGustavo F. Padovan 
47445b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
47459f69bda6SGustavo F. Padovan 
474689bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
47479f69bda6SGustavo F. Padovan 		goto drop;
47489f69bda6SGustavo F. Padovan 
4749e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
47509f69bda6SGustavo F. Padovan 		goto drop;
47519f69bda6SGustavo F. Padovan 
475223070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
47535b4cedaaSAndrei Emeltchenko 		return 0;
47549f69bda6SGustavo F. Padovan 
47559f69bda6SGustavo F. Padovan drop:
47569f69bda6SGustavo F. Padovan 	kfree_skb(skb);
47579f69bda6SGustavo F. Padovan 
47589f69bda6SGustavo F. Padovan 	return 0;
47599f69bda6SGustavo F. Padovan }
47609f69bda6SGustavo F. Padovan 
47610a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
47620a708f8fSGustavo F. Padovan {
47630a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
47640a708f8fSGustavo F. Padovan 	u16 cid, len;
47650a708f8fSGustavo F. Padovan 	__le16 psm;
47660a708f8fSGustavo F. Padovan 
47670a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
47680a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
47690a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
47700a708f8fSGustavo F. Padovan 
47710a708f8fSGustavo F. Padovan 	if (len != skb->len) {
47720a708f8fSGustavo F. Padovan 		kfree_skb(skb);
47730a708f8fSGustavo F. Padovan 		return;
47740a708f8fSGustavo F. Padovan 	}
47750a708f8fSGustavo F. Padovan 
47760a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
47770a708f8fSGustavo F. Padovan 
47780a708f8fSGustavo F. Padovan 	switch (cid) {
47793300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
47800a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
47810a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
47820a708f8fSGustavo F. Padovan 		break;
47830a708f8fSGustavo F. Padovan 
47840a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4785097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
47860a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
47870a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
47880a708f8fSGustavo F. Padovan 		break;
47890a708f8fSGustavo F. Padovan 
47909f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
47919f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
47929f69bda6SGustavo F. Padovan 		break;
47939f69bda6SGustavo F. Padovan 
4794b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4795b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4796b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4797b501d6a1SAnderson Briglia 		break;
4798b501d6a1SAnderson Briglia 
47990a708f8fSGustavo F. Padovan 	default:
48000a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
48010a708f8fSGustavo F. Padovan 		break;
48020a708f8fSGustavo F. Padovan 	}
48030a708f8fSGustavo F. Padovan }
48040a708f8fSGustavo F. Padovan 
48050a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
48060a708f8fSGustavo F. Padovan 
4807686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
48080a708f8fSGustavo F. Padovan {
48090a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
481023691d75SGustavo F. Padovan 	struct l2cap_chan *c;
48110a708f8fSGustavo F. Padovan 
48120a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
48130a708f8fSGustavo F. Padovan 
48140a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
481523691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
481623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
481723691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
48184343478fSGustavo F. Padovan 
481989bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
48200a708f8fSGustavo F. Padovan 			continue;
48210a708f8fSGustavo F. Padovan 
48220a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
48230a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
482443bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
48250a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
48260a708f8fSGustavo F. Padovan 			exact++;
48270a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
48280a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
482943bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
48300a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
48310a708f8fSGustavo F. Padovan 		}
48320a708f8fSGustavo F. Padovan 	}
483323691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
48340a708f8fSGustavo F. Padovan 
48350a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
48360a708f8fSGustavo F. Padovan }
48370a708f8fSGustavo F. Padovan 
4838686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
48390a708f8fSGustavo F. Padovan {
48400a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
48410a708f8fSGustavo F. Padovan 
48420a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
48430a708f8fSGustavo F. Padovan 
48440a708f8fSGustavo F. Padovan 	if (!status) {
48450a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
48460a708f8fSGustavo F. Padovan 		if (conn)
48470a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
48480a708f8fSGustavo F. Padovan 	} else
4849e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
48500a708f8fSGustavo F. Padovan 
48510a708f8fSGustavo F. Padovan 	return 0;
48520a708f8fSGustavo F. Padovan }
48530a708f8fSGustavo F. Padovan 
4854686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
48550a708f8fSGustavo F. Padovan {
48560a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
48570a708f8fSGustavo F. Padovan 
48580a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
48590a708f8fSGustavo F. Padovan 
4860686ebf28SUlisses Furquim 	if (!conn)
48619f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
48620a708f8fSGustavo F. Padovan 	return conn->disc_reason;
48630a708f8fSGustavo F. Padovan }
48640a708f8fSGustavo F. Padovan 
4865686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
48660a708f8fSGustavo F. Padovan {
48670a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
48680a708f8fSGustavo F. Padovan 
4869e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
48700a708f8fSGustavo F. Padovan 	return 0;
48710a708f8fSGustavo F. Padovan }
48720a708f8fSGustavo F. Padovan 
48734343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
48740a708f8fSGustavo F. Padovan {
4875715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
48760a708f8fSGustavo F. Padovan 		return;
48770a708f8fSGustavo F. Padovan 
48780a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
48794343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4880ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
48814343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
48820f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
48830a708f8fSGustavo F. Padovan 	} else {
48844343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4885c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
48860a708f8fSGustavo F. Padovan 	}
48870a708f8fSGustavo F. Padovan }
48880a708f8fSGustavo F. Padovan 
4889686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
48900a708f8fSGustavo F. Padovan {
48910a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
489248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
48930a708f8fSGustavo F. Padovan 
48940a708f8fSGustavo F. Padovan 	if (!conn)
48950a708f8fSGustavo F. Padovan 		return 0;
48960a708f8fSGustavo F. Padovan 
48970a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
48980a708f8fSGustavo F. Padovan 
4899160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
490035d4adccSHemant Gupta 		if (!status && encrypt)
4901160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
490217cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4903160dc6acSVinicius Costa Gomes 	}
4904160dc6acSVinicius Costa Gomes 
49053df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
49060a708f8fSGustavo F. Padovan 
49073df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
49086be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
49090a708f8fSGustavo F. Padovan 
4910f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4911f1cb9af5SVinicius Costa Gomes 
4912f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4913f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4914f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4915cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4916f1cb9af5SVinicius Costa Gomes 			}
4917f1cb9af5SVinicius Costa Gomes 
49186be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4919f1cb9af5SVinicius Costa Gomes 			continue;
4920f1cb9af5SVinicius Costa Gomes 		}
4921f1cb9af5SVinicius Costa Gomes 
4922c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
49236be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
49240a708f8fSGustavo F. Padovan 			continue;
49250a708f8fSGustavo F. Padovan 		}
49260a708f8fSGustavo F. Padovan 
492789bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
492889bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
4929a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
4930a7d7723aSGustavo Padovan 
4931a7d7723aSGustavo Padovan 			bt_sk(sk)->suspended = false;
4932a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
4933a7d7723aSGustavo Padovan 
49344343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
49356be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
49360a708f8fSGustavo F. Padovan 			continue;
49370a708f8fSGustavo F. Padovan 		}
49380a708f8fSGustavo F. Padovan 
493989bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
49400a708f8fSGustavo F. Padovan 			if (!status) {
49419b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
49420a708f8fSGustavo F. Padovan 			} else {
4943ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
49440a708f8fSGustavo F. Padovan 			}
494589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
49466be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
49470a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4948df3c3931SJohan Hedberg 			__u16 res, stat;
49490a708f8fSGustavo F. Padovan 
49506be36555SAndrei Emeltchenko 			lock_sock(sk);
49516be36555SAndrei Emeltchenko 
49520a708f8fSGustavo F. Padovan 			if (!status) {
4953df3c3931SJohan Hedberg 				if (bt_sk(sk)->defer_setup) {
4954df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4955df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4956df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
495705e9a2f6SIlia Kolomisnky 					if (parent)
4958df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4959df3c3931SJohan Hedberg 				} else {
49600e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4961df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4962df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4963df3c3931SJohan Hedberg 				}
49640a708f8fSGustavo F. Padovan 			} else {
49650e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4966ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4967df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4968df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
49690a708f8fSGustavo F. Padovan 			}
49700a708f8fSGustavo F. Padovan 
49716be36555SAndrei Emeltchenko 			release_sock(sk);
49726be36555SAndrei Emeltchenko 
4973fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4974fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4975df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4976df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4977fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4978fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
49790a708f8fSGustavo F. Padovan 		}
49800a708f8fSGustavo F. Padovan 
49816be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
49820a708f8fSGustavo F. Padovan 	}
49830a708f8fSGustavo F. Padovan 
49843df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
49850a708f8fSGustavo F. Padovan 
49860a708f8fSGustavo F. Padovan 	return 0;
49870a708f8fSGustavo F. Padovan }
49880a708f8fSGustavo F. Padovan 
4989686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
49900a708f8fSGustavo F. Padovan {
49910a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
49920a708f8fSGustavo F. Padovan 
49930a708f8fSGustavo F. Padovan 	if (!conn)
49940a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
49950a708f8fSGustavo F. Padovan 
49960a708f8fSGustavo F. Padovan 	if (!conn)
49970a708f8fSGustavo F. Padovan 		goto drop;
49980a708f8fSGustavo F. Padovan 
49990a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
50000a708f8fSGustavo F. Padovan 
50010a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
50020a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
500348454079SGustavo F. Padovan 		struct l2cap_chan *chan;
50040a708f8fSGustavo F. Padovan 		u16 cid;
50050a708f8fSGustavo F. Padovan 		int len;
50060a708f8fSGustavo F. Padovan 
50070a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
50080a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
50090a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
50100a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50110a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
50120a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50130a708f8fSGustavo F. Padovan 		}
50140a708f8fSGustavo F. Padovan 
50150a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
50160a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
50170a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
50180a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50190a708f8fSGustavo F. Padovan 			goto drop;
50200a708f8fSGustavo F. Padovan 		}
50210a708f8fSGustavo F. Padovan 
50220a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
50230a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
50240a708f8fSGustavo F. Padovan 		cid = __le16_to_cpu(hdr->cid);
50250a708f8fSGustavo F. Padovan 
50260a708f8fSGustavo F. Padovan 		if (len == skb->len) {
50270a708f8fSGustavo F. Padovan 			/* Complete frame received */
50280a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
50290a708f8fSGustavo F. Padovan 			return 0;
50300a708f8fSGustavo F. Padovan 		}
50310a708f8fSGustavo F. Padovan 
50320a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
50330a708f8fSGustavo F. Padovan 
50340a708f8fSGustavo F. Padovan 		if (skb->len > len) {
50350a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
50360a708f8fSGustavo F. Padovan 				skb->len, len);
50370a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50380a708f8fSGustavo F. Padovan 			goto drop;
50390a708f8fSGustavo F. Padovan 		}
50400a708f8fSGustavo F. Padovan 
5041baa7e1faSGustavo F. Padovan 		chan = l2cap_get_chan_by_scid(conn, cid);
50420a708f8fSGustavo F. Padovan 
504348454079SGustavo F. Padovan 		if (chan && chan->sk) {
504448454079SGustavo F. Padovan 			struct sock *sk = chan->sk;
50453df91ea2SAndrei Emeltchenko 			lock_sock(sk);
504648454079SGustavo F. Padovan 
50470c1bc5c6SGustavo F. Padovan 			if (chan->imtu < len - L2CAP_HDR_SIZE) {
504848454079SGustavo F. Padovan 				BT_ERR("Frame exceeding recv MTU (len %d, "
504948454079SGustavo F. Padovan 							"MTU %d)", len,
50500c1bc5c6SGustavo F. Padovan 							chan->imtu);
5051aa2ac881SGustavo F. Padovan 				release_sock(sk);
50520a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
50530a708f8fSGustavo F. Padovan 				goto drop;
50540a708f8fSGustavo F. Padovan 			}
5055aa2ac881SGustavo F. Padovan 			release_sock(sk);
505648454079SGustavo F. Padovan 		}
50570a708f8fSGustavo F. Padovan 
50580a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
50590a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
50600a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
50610a708f8fSGustavo F. Padovan 			goto drop;
50620a708f8fSGustavo F. Padovan 
50630a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50640a708f8fSGustavo F. Padovan 								skb->len);
50650a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
50660a708f8fSGustavo F. Padovan 	} else {
50670a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
50680a708f8fSGustavo F. Padovan 
50690a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50700a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
50710a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50720a708f8fSGustavo F. Padovan 			goto drop;
50730a708f8fSGustavo F. Padovan 		}
50740a708f8fSGustavo F. Padovan 
50750a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
50760a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
50770a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
50780a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
50790a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50800a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
50810a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50820a708f8fSGustavo F. Padovan 			goto drop;
50830a708f8fSGustavo F. Padovan 		}
50840a708f8fSGustavo F. Padovan 
50850a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50860a708f8fSGustavo F. Padovan 								skb->len);
50870a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
50880a708f8fSGustavo F. Padovan 
50890a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50900a708f8fSGustavo F. Padovan 			/* Complete frame received */
50910a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
50920a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50930a708f8fSGustavo F. Padovan 		}
50940a708f8fSGustavo F. Padovan 	}
50950a708f8fSGustavo F. Padovan 
50960a708f8fSGustavo F. Padovan drop:
50970a708f8fSGustavo F. Padovan 	kfree_skb(skb);
50980a708f8fSGustavo F. Padovan 	return 0;
50990a708f8fSGustavo F. Padovan }
51000a708f8fSGustavo F. Padovan 
51010a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
51020a708f8fSGustavo F. Padovan {
510323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
51040a708f8fSGustavo F. Padovan 
5105333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
51060a708f8fSGustavo F. Padovan 
510723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
510823691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
51090a708f8fSGustavo F. Padovan 
5110903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
51110a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
51120a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
511389bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
511423691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
511523691d75SGustavo F. Padovan 					c->sec_level, c->mode);
51160a708f8fSGustavo F. Padovan 	}
51170a708f8fSGustavo F. Padovan 
5118333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
51190a708f8fSGustavo F. Padovan 
51200a708f8fSGustavo F. Padovan 	return 0;
51210a708f8fSGustavo F. Padovan }
51220a708f8fSGustavo F. Padovan 
51230a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
51240a708f8fSGustavo F. Padovan {
51250a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
51260a708f8fSGustavo F. Padovan }
51270a708f8fSGustavo F. Padovan 
51280a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
51290a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
51300a708f8fSGustavo F. Padovan 	.read		= seq_read,
51310a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
51320a708f8fSGustavo F. Padovan 	.release	= single_release,
51330a708f8fSGustavo F. Padovan };
51340a708f8fSGustavo F. Padovan 
51350a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
51360a708f8fSGustavo F. Padovan 
513764274518SGustavo F. Padovan int __init l2cap_init(void)
51380a708f8fSGustavo F. Padovan {
51390a708f8fSGustavo F. Padovan 	int err;
51400a708f8fSGustavo F. Padovan 
5141bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
51420a708f8fSGustavo F. Padovan 	if (err < 0)
51430a708f8fSGustavo F. Padovan 		return err;
51440a708f8fSGustavo F. Padovan 
51450a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
51460a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
51470a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
51480a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
51490a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
51500a708f8fSGustavo F. Padovan 	}
51510a708f8fSGustavo F. Padovan 
51520a708f8fSGustavo F. Padovan 	return 0;
51530a708f8fSGustavo F. Padovan }
51540a708f8fSGustavo F. Padovan 
515564274518SGustavo F. Padovan void l2cap_exit(void)
51560a708f8fSGustavo F. Padovan {
51570a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5158bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
51590a708f8fSGustavo F. Padovan }
51600a708f8fSGustavo F. Padovan 
51610a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
51620a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5163