xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 61d6ef3e)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
70a708f8fSGustavo F. Padovan 
80a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
90a708f8fSGustavo F. Padovan 
100a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
110a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
120a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
130a708f8fSGustavo F. Padovan 
140a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
150a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
160a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
170a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
180a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
190a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
200a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
210a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
220a708f8fSGustavo F. Padovan 
230a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
240a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
250a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
260a708f8fSGustavo F. Padovan */
270a708f8fSGustavo F. Padovan 
28bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
290a708f8fSGustavo F. Padovan 
300a708f8fSGustavo F. Padovan #include <linux/module.h>
310a708f8fSGustavo F. Padovan 
320a708f8fSGustavo F. Padovan #include <linux/types.h>
330a708f8fSGustavo F. Padovan #include <linux/capability.h>
340a708f8fSGustavo F. Padovan #include <linux/errno.h>
350a708f8fSGustavo F. Padovan #include <linux/kernel.h>
360a708f8fSGustavo F. Padovan #include <linux/sched.h>
370a708f8fSGustavo F. Padovan #include <linux/slab.h>
380a708f8fSGustavo F. Padovan #include <linux/poll.h>
390a708f8fSGustavo F. Padovan #include <linux/fcntl.h>
400a708f8fSGustavo F. Padovan #include <linux/init.h>
410a708f8fSGustavo F. Padovan #include <linux/interrupt.h>
420a708f8fSGustavo F. Padovan #include <linux/socket.h>
430a708f8fSGustavo F. Padovan #include <linux/skbuff.h>
440a708f8fSGustavo F. Padovan #include <linux/list.h>
450a708f8fSGustavo F. Padovan #include <linux/device.h>
460a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
470a708f8fSGustavo F. Padovan #include <linux/seq_file.h>
480a708f8fSGustavo F. Padovan #include <linux/uaccess.h>
490a708f8fSGustavo F. Padovan #include <linux/crc16.h>
500a708f8fSGustavo F. Padovan #include <net/sock.h>
510a708f8fSGustavo F. Padovan 
520a708f8fSGustavo F. Padovan #include <asm/unaligned.h>
530a708f8fSGustavo F. Padovan 
540a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
550a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
560a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
57b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
580a708f8fSGustavo F. Padovan 
59eb939922SRusty Russell bool disable_ertm;
600a708f8fSGustavo F. Padovan 
610a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
6250a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
630a708f8fSGustavo F. Padovan 
64b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
65b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
660a708f8fSGustavo F. Padovan 
670a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
680a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
694519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
704519de9aSGustavo F. Padovan 								void *data);
71710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
724519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
734519de9aSGustavo F. Padovan 				struct l2cap_chan *chan, int err);
740a708f8fSGustavo F. Padovan 
750a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7671ba0e56SGustavo F. Padovan 
77baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
780a708f8fSGustavo F. Padovan {
793df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
80baa7e1faSGustavo F. Padovan 
813df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
823df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
833df91ea2SAndrei Emeltchenko 			return c;
840a708f8fSGustavo F. Padovan 	}
853df91ea2SAndrei Emeltchenko 	return NULL;
86baa7e1faSGustavo F. Padovan }
870a708f8fSGustavo F. Padovan 
88baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
890a708f8fSGustavo F. Padovan {
903df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
91baa7e1faSGustavo F. Padovan 
923df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
933df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
943df91ea2SAndrei Emeltchenko 			return c;
950a708f8fSGustavo F. Padovan 	}
963df91ea2SAndrei Emeltchenko 	return NULL;
97baa7e1faSGustavo F. Padovan }
980a708f8fSGustavo F. Padovan 
990a708f8fSGustavo F. Padovan /* Find channel with given SCID.
1000a708f8fSGustavo F. Padovan  * Returns locked socket */
101baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
1020a708f8fSGustavo F. Padovan {
10348454079SGustavo F. Padovan 	struct l2cap_chan *c;
104baa7e1faSGustavo F. Padovan 
1053df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
106baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
1073df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1083df91ea2SAndrei Emeltchenko 
10948454079SGustavo F. Padovan 	return c;
1100a708f8fSGustavo F. Padovan }
1110a708f8fSGustavo F. Padovan 
112baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1130a708f8fSGustavo F. Padovan {
1143df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
115baa7e1faSGustavo F. Padovan 
1163df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1173df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1183df91ea2SAndrei Emeltchenko 			return c;
1190a708f8fSGustavo F. Padovan 	}
1203df91ea2SAndrei Emeltchenko 	return NULL;
121baa7e1faSGustavo F. Padovan }
1220a708f8fSGustavo F. Padovan 
12323691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1249e4425ffSGustavo F. Padovan {
12523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1269e4425ffSGustavo F. Padovan 
12723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
12823691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
12923691d75SGustavo F. Padovan 			return c;
1309e4425ffSGustavo F. Padovan 	}
131250938cbSSzymon Janc 	return NULL;
132250938cbSSzymon Janc }
1339e4425ffSGustavo F. Padovan 
1349e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1359e4425ffSGustavo F. Padovan {
13673b2ec18SGustavo F. Padovan 	int err;
13773b2ec18SGustavo F. Padovan 
138333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1399e4425ffSGustavo F. Padovan 
14023691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
14173b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
14273b2ec18SGustavo F. Padovan 		goto done;
1439e4425ffSGustavo F. Padovan 	}
1449e4425ffSGustavo F. Padovan 
14573b2ec18SGustavo F. Padovan 	if (psm) {
1469e4425ffSGustavo F. Padovan 		chan->psm = psm;
1479e4425ffSGustavo F. Padovan 		chan->sport = psm;
14873b2ec18SGustavo F. Padovan 		err = 0;
14973b2ec18SGustavo F. Padovan 	} else {
15073b2ec18SGustavo F. Padovan 		u16 p;
1519e4425ffSGustavo F. Padovan 
15273b2ec18SGustavo F. Padovan 		err = -EINVAL;
15373b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
15423691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
15573b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
15673b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
15773b2ec18SGustavo F. Padovan 				err = 0;
15873b2ec18SGustavo F. Padovan 				break;
15973b2ec18SGustavo F. Padovan 			}
16073b2ec18SGustavo F. Padovan 	}
16173b2ec18SGustavo F. Padovan 
16273b2ec18SGustavo F. Padovan done:
163333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
16473b2ec18SGustavo F. Padovan 	return err;
1659e4425ffSGustavo F. Padovan }
1669e4425ffSGustavo F. Padovan 
1679e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1689e4425ffSGustavo F. Padovan {
169333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1709e4425ffSGustavo F. Padovan 
1719e4425ffSGustavo F. Padovan 	chan->scid = scid;
1729e4425ffSGustavo F. Padovan 
173333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1749e4425ffSGustavo F. Padovan 
1759e4425ffSGustavo F. Padovan 	return 0;
1769e4425ffSGustavo F. Padovan }
1779e4425ffSGustavo F. Padovan 
178baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1790a708f8fSGustavo F. Padovan {
1800a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1810a708f8fSGustavo F. Padovan 
1820a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
183baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1840a708f8fSGustavo F. Padovan 			return cid;
1850a708f8fSGustavo F. Padovan 	}
1860a708f8fSGustavo F. Padovan 
1870a708f8fSGustavo F. Padovan 	return 0;
1880a708f8fSGustavo F. Padovan }
1890a708f8fSGustavo F. Padovan 
1900e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
19189bc500eSGustavo F. Padovan {
19242d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
193badaaa00SGustavo F. Padovan 						state_to_string(state));
194badaaa00SGustavo F. Padovan 
19589bc500eSGustavo F. Padovan 	chan->state = state;
19689bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
19789bc500eSGustavo F. Padovan }
19889bc500eSGustavo F. Padovan 
1990e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
2000e587be7SAndrei Emeltchenko {
2010e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2020e587be7SAndrei Emeltchenko 
2030e587be7SAndrei Emeltchenko 	lock_sock(sk);
2040e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
2050e587be7SAndrei Emeltchenko 	release_sock(sk);
2060e587be7SAndrei Emeltchenko }
2070e587be7SAndrei Emeltchenko 
2082e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2092e0052e4SAndrei Emeltchenko {
2102e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2112e0052e4SAndrei Emeltchenko 
2122e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2132e0052e4SAndrei Emeltchenko }
2142e0052e4SAndrei Emeltchenko 
2152e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2162e0052e4SAndrei Emeltchenko {
2172e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2182e0052e4SAndrei Emeltchenko 
2192e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2202e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2212e0052e4SAndrei Emeltchenko 	release_sock(sk);
2222e0052e4SAndrei Emeltchenko }
2232e0052e4SAndrei Emeltchenko 
2243c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2253c588192SMat Martineau 
2263c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2273c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2283c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2293c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2303c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2313c588192SMat Martineau  * and removed from the head in constant time, without further memory
2323c588192SMat Martineau  * allocs or frees.
2333c588192SMat Martineau  */
2343c588192SMat Martineau 
2353c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2363c588192SMat Martineau {
2373c588192SMat Martineau 	size_t alloc_size, i;
2383c588192SMat Martineau 
2393c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2403c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2413c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2423c588192SMat Martineau 	 */
2433c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2443c588192SMat Martineau 
2453c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2463c588192SMat Martineau 	if (!seq_list->list)
2473c588192SMat Martineau 		return -ENOMEM;
2483c588192SMat Martineau 
2493c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2503c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2513c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2523c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2533c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2543c588192SMat Martineau 
2553c588192SMat Martineau 	return 0;
2563c588192SMat Martineau }
2573c588192SMat Martineau 
2583c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2593c588192SMat Martineau {
2603c588192SMat Martineau 	kfree(seq_list->list);
2613c588192SMat Martineau }
2623c588192SMat Martineau 
2633c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2643c588192SMat Martineau 					   u16 seq)
2653c588192SMat Martineau {
2663c588192SMat Martineau 	/* Constant-time check for list membership */
2673c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2683c588192SMat Martineau }
2693c588192SMat Martineau 
2703c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2713c588192SMat Martineau {
2723c588192SMat Martineau 	u16 mask = seq_list->mask;
2733c588192SMat Martineau 
2743c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2753c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2763c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2773c588192SMat Martineau 	} else if (seq_list->head == seq) {
2783c588192SMat Martineau 		/* Head can be removed in constant time */
2793c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2803c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2813c588192SMat Martineau 
2823c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
2833c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2843c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2853c588192SMat Martineau 		}
2863c588192SMat Martineau 	} else {
2873c588192SMat Martineau 		/* Walk the list to find the sequence number */
2883c588192SMat Martineau 		u16 prev = seq_list->head;
2893c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
2903c588192SMat Martineau 			prev = seq_list->list[prev & mask];
2913c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
2923c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
2933c588192SMat Martineau 		}
2943c588192SMat Martineau 
2953c588192SMat Martineau 		/* Unlink the number from the list and clear it */
2963c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
2973c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2983c588192SMat Martineau 		if (seq_list->tail == seq)
2993c588192SMat Martineau 			seq_list->tail = prev;
3003c588192SMat Martineau 	}
3013c588192SMat Martineau 	return seq;
3023c588192SMat Martineau }
3033c588192SMat Martineau 
3043c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3053c588192SMat Martineau {
3063c588192SMat Martineau 	/* Remove the head in constant time */
3073c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3083c588192SMat Martineau }
3093c588192SMat Martineau 
3103c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3113c588192SMat Martineau {
3123c588192SMat Martineau 	if (seq_list->head != L2CAP_SEQ_LIST_CLEAR) {
3133c588192SMat Martineau 		u16 i;
3143c588192SMat Martineau 		for (i = 0; i <= seq_list->mask; i++)
3153c588192SMat Martineau 			seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3163c588192SMat Martineau 
3173c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3183c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3193c588192SMat Martineau 	}
3203c588192SMat Martineau }
3213c588192SMat Martineau 
3223c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3233c588192SMat Martineau {
3243c588192SMat Martineau 	u16 mask = seq_list->mask;
3253c588192SMat Martineau 
3263c588192SMat Martineau 	/* All appends happen in constant time */
3273c588192SMat Martineau 
3283c588192SMat Martineau 	if (seq_list->list[seq & mask] == L2CAP_SEQ_LIST_CLEAR) {
3293c588192SMat Martineau 		if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3303c588192SMat Martineau 			seq_list->head = seq;
3313c588192SMat Martineau 		else
3323c588192SMat Martineau 			seq_list->list[seq_list->tail & mask] = seq;
3333c588192SMat Martineau 
3343c588192SMat Martineau 		seq_list->tail = seq;
3353c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3363c588192SMat Martineau 	}
3373c588192SMat Martineau }
3383c588192SMat Martineau 
339721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
340ab07801dSGustavo F. Padovan {
341721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
342721c4181SGustavo F. Padovan 							chan_timer.work);
3433df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
344ab07801dSGustavo F. Padovan 	int reason;
345ab07801dSGustavo F. Padovan 
346e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
347ab07801dSGustavo F. Padovan 
3483df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3496be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
350ab07801dSGustavo F. Padovan 
35189bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
352ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
35389bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
354ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
355ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
356ab07801dSGustavo F. Padovan 	else
357ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
358ab07801dSGustavo F. Padovan 
3590f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
360ab07801dSGustavo F. Padovan 
3616be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
362ab07801dSGustavo F. Padovan 
363ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3643df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3653df91ea2SAndrei Emeltchenko 
366371fd835SUlisses Furquim 	l2cap_chan_put(chan);
367ab07801dSGustavo F. Padovan }
368ab07801dSGustavo F. Padovan 
369eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3700a708f8fSGustavo F. Padovan {
37148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3720a708f8fSGustavo F. Padovan 
37348454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
37448454079SGustavo F. Padovan 	if (!chan)
37548454079SGustavo F. Padovan 		return NULL;
3760a708f8fSGustavo F. Padovan 
377c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
378c03b355eSAndrei Emeltchenko 
379333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
38023691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
381333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
38223691d75SGustavo F. Padovan 
383721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
384ab07801dSGustavo F. Padovan 
38589bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
38689bc500eSGustavo F. Padovan 
38771ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
38871ba0e56SGustavo F. Padovan 
389eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
390abc545b8SSzymon Janc 
39148454079SGustavo F. Padovan 	return chan;
3920a708f8fSGustavo F. Padovan }
3930a708f8fSGustavo F. Padovan 
39423691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
3956ff5abbfSGustavo F. Padovan {
396333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
39723691d75SGustavo F. Padovan 	list_del(&chan->global_l);
398333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
39923691d75SGustavo F. Padovan 
400371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4016ff5abbfSGustavo F. Padovan }
4026ff5abbfSGustavo F. Padovan 
403bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
404bd4b1653SAndrei Emeltchenko {
405bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
406bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
407bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
408bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
409bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
410bd4b1653SAndrei Emeltchenko 
411bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
412bd4b1653SAndrei Emeltchenko }
413bd4b1653SAndrei Emeltchenko 
41414a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4150a708f8fSGustavo F. Padovan {
4160a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
417097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4180a708f8fSGustavo F. Padovan 
4199f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4200a708f8fSGustavo F. Padovan 
4218c1d787bSGustavo F. Padovan 	chan->conn = conn;
4220a708f8fSGustavo F. Padovan 
4235491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4245491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
425b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
426b62f328bSVille Tervo 			/* LE connection */
4270c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
428fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
429fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
430b62f328bSVille Tervo 		} else {
4310a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
432fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4330c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
434b62f328bSVille Tervo 		}
4355491120eSAndrei Emeltchenko 		break;
4365491120eSAndrei Emeltchenko 
4375491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4380a708f8fSGustavo F. Padovan 		/* Connectionless socket */
439fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
440fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4410c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4425491120eSAndrei Emeltchenko 		break;
4435491120eSAndrei Emeltchenko 
4445491120eSAndrei Emeltchenko 	default:
4450a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
446fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
447fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4480c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4490a708f8fSGustavo F. Padovan 	}
4500a708f8fSGustavo F. Padovan 
4518f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4528f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4538f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4548f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4558f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4568f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4578f7975b1SAndrei Emeltchenko 
458371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
459baa7e1faSGustavo F. Padovan 
4603df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
461643162a8SAndrei Emeltchenko }
462643162a8SAndrei Emeltchenko 
46314a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
464643162a8SAndrei Emeltchenko {
465643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
466643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4673df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4680a708f8fSGustavo F. Padovan }
4690a708f8fSGustavo F. Padovan 
4704519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4710a708f8fSGustavo F. Padovan {
47248454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4738c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4740a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
4750a708f8fSGustavo F. Padovan 
476c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
4770a708f8fSGustavo F. Padovan 
47849208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
4790a708f8fSGustavo F. Padovan 
4800a708f8fSGustavo F. Padovan 	if (conn) {
481baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
4823df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
4833d57dc68SGustavo F. Padovan 
484371fd835SUlisses Furquim 		l2cap_chan_put(chan);
485baa7e1faSGustavo F. Padovan 
4868c1d787bSGustavo F. Padovan 		chan->conn = NULL;
4870a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
4880a708f8fSGustavo F. Padovan 	}
4890a708f8fSGustavo F. Padovan 
4906be36555SAndrei Emeltchenko 	lock_sock(sk);
4916be36555SAndrei Emeltchenko 
4920e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
4930a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
4940a708f8fSGustavo F. Padovan 
4950a708f8fSGustavo F. Padovan 	if (err)
4962e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
4970a708f8fSGustavo F. Padovan 
4980a708f8fSGustavo F. Padovan 	if (parent) {
4990a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5000a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5010a708f8fSGustavo F. Padovan 	} else
5020a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5030a708f8fSGustavo F. Padovan 
5046be36555SAndrei Emeltchenko 	release_sock(sk);
5056be36555SAndrei Emeltchenko 
506c1360a1cSGustavo F. Padovan 	if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
507c1360a1cSGustavo F. Padovan 			test_bit(CONF_INPUT_DONE, &chan->conf_state)))
5086ff5abbfSGustavo F. Padovan 		return;
5092ead70b8SGustavo F. Padovan 
51058d35f87SGustavo F. Padovan 	skb_queue_purge(&chan->tx_q);
5110a708f8fSGustavo F. Padovan 
5120c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
5130a708f8fSGustavo F. Padovan 		struct srej_list *l, *tmp;
5140a708f8fSGustavo F. Padovan 
5151a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5161a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5171a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5180a708f8fSGustavo F. Padovan 
519f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5200a708f8fSGustavo F. Padovan 
5213c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5223c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
52339d5a3eeSGustavo F. Padovan 		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
5240a708f8fSGustavo F. Padovan 			list_del(&l->list);
5250a708f8fSGustavo F. Padovan 			kfree(l);
5260a708f8fSGustavo F. Padovan 		}
5270a708f8fSGustavo F. Padovan 	}
5280a708f8fSGustavo F. Padovan }
5290a708f8fSGustavo F. Padovan 
5304519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5314519de9aSGustavo F. Padovan {
5324519de9aSGustavo F. Padovan 	struct sock *sk;
5334519de9aSGustavo F. Padovan 
5344519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5354519de9aSGustavo F. Padovan 
5364519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5370f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
538ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5393df91ea2SAndrei Emeltchenko 
5406be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
541c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
542ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5436be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5443df91ea2SAndrei Emeltchenko 
545ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5460f852724SGustavo F. Padovan 	}
5474519de9aSGustavo F. Padovan }
5484519de9aSGustavo F. Padovan 
5490f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5504519de9aSGustavo F. Padovan {
5514519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5524519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5534519de9aSGustavo F. Padovan 
554e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
555e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5564519de9aSGustavo F. Padovan 
55789bc500eSGustavo F. Padovan 	switch (chan->state) {
5584519de9aSGustavo F. Padovan 	case BT_LISTEN:
5596be36555SAndrei Emeltchenko 		lock_sock(sk);
5604519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
56189bc500eSGustavo F. Padovan 
5620e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
56389bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5646be36555SAndrei Emeltchenko 		release_sock(sk);
5654519de9aSGustavo F. Padovan 		break;
5664519de9aSGustavo F. Padovan 
5674519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5684519de9aSGustavo F. Padovan 	case BT_CONFIG:
569715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5704519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
571c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5724519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5734519de9aSGustavo F. Padovan 		} else
5744519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5754519de9aSGustavo F. Padovan 		break;
5764519de9aSGustavo F. Padovan 
5774519de9aSGustavo F. Padovan 	case BT_CONNECT2:
578715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5794519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5804519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5814519de9aSGustavo F. Padovan 			__u16 result;
5824519de9aSGustavo F. Padovan 
5834519de9aSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup)
5844519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
5854519de9aSGustavo F. Padovan 			else
5864519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
58789bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
5884519de9aSGustavo F. Padovan 
5894519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5904519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5914519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
5924519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
5934519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5944519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
5954519de9aSGustavo F. Padovan 		}
5964519de9aSGustavo F. Padovan 
5974519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
5984519de9aSGustavo F. Padovan 		break;
5994519de9aSGustavo F. Padovan 
6004519de9aSGustavo F. Padovan 	case BT_CONNECT:
6014519de9aSGustavo F. Padovan 	case BT_DISCONN:
6024519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6034519de9aSGustavo F. Padovan 		break;
6044519de9aSGustavo F. Padovan 
6054519de9aSGustavo F. Padovan 	default:
6066be36555SAndrei Emeltchenko 		lock_sock(sk);
6074519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6086be36555SAndrei Emeltchenko 		release_sock(sk);
6094519de9aSGustavo F. Padovan 		break;
6104519de9aSGustavo F. Padovan 	}
6114519de9aSGustavo F. Padovan }
6124519de9aSGustavo F. Padovan 
6134343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6140a708f8fSGustavo F. Padovan {
615715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6164343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6170a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6180a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6190a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6200a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6210a708f8fSGustavo F. Padovan 		default:
6220a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6230a708f8fSGustavo F. Padovan 		}
624fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6254343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6264343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6270a708f8fSGustavo F. Padovan 
6284343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6290a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6300a708f8fSGustavo F. Padovan 		else
6310a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6320a708f8fSGustavo F. Padovan 	} else {
6334343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6340a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6350a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6360a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6370a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6380a708f8fSGustavo F. Padovan 		default:
6390a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6400a708f8fSGustavo F. Padovan 		}
6410a708f8fSGustavo F. Padovan 	}
6420a708f8fSGustavo F. Padovan }
6430a708f8fSGustavo F. Padovan 
6440a708f8fSGustavo F. Padovan /* Service level security */
645d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6460a708f8fSGustavo F. Padovan {
6478c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6480a708f8fSGustavo F. Padovan 	__u8 auth_type;
6490a708f8fSGustavo F. Padovan 
6504343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6510a708f8fSGustavo F. Padovan 
6524343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6530a708f8fSGustavo F. Padovan }
6540a708f8fSGustavo F. Padovan 
655b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6560a708f8fSGustavo F. Padovan {
6570a708f8fSGustavo F. Padovan 	u8 id;
6580a708f8fSGustavo F. Padovan 
6590a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6600a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6610a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6620a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6630a708f8fSGustavo F. Padovan 	 */
6640a708f8fSGustavo F. Padovan 
665333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6660a708f8fSGustavo F. Padovan 
6670a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6680a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6690a708f8fSGustavo F. Padovan 
6700a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6710a708f8fSGustavo F. Padovan 
672333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6730a708f8fSGustavo F. Padovan 
6740a708f8fSGustavo F. Padovan 	return id;
6750a708f8fSGustavo F. Padovan }
6760a708f8fSGustavo F. Padovan 
6774519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6780a708f8fSGustavo F. Padovan {
6790a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6800a708f8fSGustavo F. Padovan 	u8 flags;
6810a708f8fSGustavo F. Padovan 
6820a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
6830a708f8fSGustavo F. Padovan 
6840a708f8fSGustavo F. Padovan 	if (!skb)
6850a708f8fSGustavo F. Padovan 		return;
6860a708f8fSGustavo F. Padovan 
6870a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
6880a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
6890a708f8fSGustavo F. Padovan 	else
6900a708f8fSGustavo F. Padovan 		flags = ACL_START;
6910a708f8fSGustavo F. Padovan 
69214b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
6935e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
69414b12d0bSJaikumar Ganesh 
69573d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
6960a708f8fSGustavo F. Padovan }
6970a708f8fSGustavo F. Padovan 
69873d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
69973d80debSLuiz Augusto von Dentz {
70073d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
70173d80debSLuiz Augusto von Dentz 	u16 flags;
70273d80debSLuiz Augusto von Dentz 
70373d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
70473d80debSLuiz Augusto von Dentz 							skb->priority);
70573d80debSLuiz Augusto von Dentz 
70673d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
70773d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
70873d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
70973d80debSLuiz Augusto von Dentz 	else
71073d80debSLuiz Augusto von Dentz 		flags = ACL_START;
71173d80debSLuiz Augusto von Dentz 
71273d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
71373d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7140a708f8fSGustavo F. Padovan }
7150a708f8fSGustavo F. Padovan 
716b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
717b5c6aaedSMat Martineau {
718b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
719b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
720b5c6aaedSMat Martineau 
721b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
722b5c6aaedSMat Martineau 		/* S-Frame */
723b5c6aaedSMat Martineau 		control->sframe = 1;
724b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
725b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
726b5c6aaedSMat Martineau 
727b5c6aaedSMat Martineau 		control->sar = 0;
728b5c6aaedSMat Martineau 		control->txseq = 0;
729b5c6aaedSMat Martineau 	} else {
730b5c6aaedSMat Martineau 		/* I-Frame */
731b5c6aaedSMat Martineau 		control->sframe = 0;
732b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
733b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
734b5c6aaedSMat Martineau 
735b5c6aaedSMat Martineau 		control->poll = 0;
736b5c6aaedSMat Martineau 		control->super = 0;
737b5c6aaedSMat Martineau 	}
738b5c6aaedSMat Martineau }
739b5c6aaedSMat Martineau 
740b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
741b5c6aaedSMat Martineau {
742b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
743b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
744b5c6aaedSMat Martineau 
745b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
746b5c6aaedSMat Martineau 		/* S-Frame */
747b5c6aaedSMat Martineau 		control->sframe = 1;
748b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
749b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
750b5c6aaedSMat Martineau 
751b5c6aaedSMat Martineau 		control->sar = 0;
752b5c6aaedSMat Martineau 		control->txseq = 0;
753b5c6aaedSMat Martineau 	} else {
754b5c6aaedSMat Martineau 		/* I-Frame */
755b5c6aaedSMat Martineau 		control->sframe = 0;
756b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
757b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
758b5c6aaedSMat Martineau 
759b5c6aaedSMat Martineau 		control->poll = 0;
760b5c6aaedSMat Martineau 		control->super = 0;
761b5c6aaedSMat Martineau 	}
762b5c6aaedSMat Martineau }
763b5c6aaedSMat Martineau 
764b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
765b5c6aaedSMat Martineau 				    struct sk_buff *skb)
766b5c6aaedSMat Martineau {
767b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
768b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
769b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
770b5c6aaedSMat Martineau 	} else {
771b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
772b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
773b5c6aaedSMat Martineau 	}
774b5c6aaedSMat Martineau }
775b5c6aaedSMat Martineau 
776b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
777b5c6aaedSMat Martineau {
778b5c6aaedSMat Martineau 	u32 packed;
779b5c6aaedSMat Martineau 
780b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
781b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
782b5c6aaedSMat Martineau 
783b5c6aaedSMat Martineau 	if (control->sframe) {
784b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
785b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
786b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
787b5c6aaedSMat Martineau 	} else {
788b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
789b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
790b5c6aaedSMat Martineau 	}
791b5c6aaedSMat Martineau 
792b5c6aaedSMat Martineau 	return packed;
793b5c6aaedSMat Martineau }
794b5c6aaedSMat Martineau 
795b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
796b5c6aaedSMat Martineau {
797b5c6aaedSMat Martineau 	u16 packed;
798b5c6aaedSMat Martineau 
799b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
800b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
801b5c6aaedSMat Martineau 
802b5c6aaedSMat Martineau 	if (control->sframe) {
803b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
804b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
805b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
806b5c6aaedSMat Martineau 	} else {
807b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
808b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
809b5c6aaedSMat Martineau 	}
810b5c6aaedSMat Martineau 
811b5c6aaedSMat Martineau 	return packed;
812b5c6aaedSMat Martineau }
813b5c6aaedSMat Martineau 
814b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
815b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
816b5c6aaedSMat Martineau 				  struct sk_buff *skb)
817b5c6aaedSMat Martineau {
818b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
819b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
820b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
821b5c6aaedSMat Martineau 	} else {
822b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
823b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
824b5c6aaedSMat Martineau 	}
825b5c6aaedSMat Martineau }
826b5c6aaedSMat Martineau 
82788843ab0SAndrei Emeltchenko static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
8280a708f8fSGustavo F. Padovan {
8290a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8300a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
8318c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
832e4ca6d98SAndrei Emeltchenko 	int count, hlen;
8330a708f8fSGustavo F. Padovan 
83489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
8350a708f8fSGustavo F. Padovan 		return;
8360a708f8fSGustavo F. Padovan 
837e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
838e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
839e4ca6d98SAndrei Emeltchenko 	else
840e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8410a708f8fSGustavo F. Padovan 
8420a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
84303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8440a708f8fSGustavo F. Padovan 
84588843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
8460a708f8fSGustavo F. Padovan 
8470a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, hlen);
848793c2f1cSAndrei Emeltchenko 
849793c2f1cSAndrei Emeltchenko 	control |= __set_sframe(chan);
8500a708f8fSGustavo F. Padovan 
851e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
85203f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
8530a708f8fSGustavo F. Padovan 
854e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
855e3781735SAndrei Emeltchenko 		control |= __set_ctrl_poll(chan);
8560a708f8fSGustavo F. Padovan 
8570a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
8580a708f8fSGustavo F. Padovan 	if (!skb)
8590a708f8fSGustavo F. Padovan 		return;
8600a708f8fSGustavo F. Padovan 
8610a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8620a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
863fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
86488843ab0SAndrei Emeltchenko 
86588843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
8660a708f8fSGustavo F. Padovan 
86747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
86803a51213SAndrei Emeltchenko 		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
86903a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8700a708f8fSGustavo F. Padovan 	}
8710a708f8fSGustavo F. Padovan 
87273d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
87373d80debSLuiz Augusto von Dentz 	l2cap_do_send(chan, skb);
8740a708f8fSGustavo F. Padovan }
8750a708f8fSGustavo F. Padovan 
87688843ab0SAndrei Emeltchenko static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
8770a708f8fSGustavo F. Padovan {
878e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
879ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
880e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
8810a708f8fSGustavo F. Padovan 	} else
882ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
8830a708f8fSGustavo F. Padovan 
8840b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
8850a708f8fSGustavo F. Padovan 
886525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
8870a708f8fSGustavo F. Padovan }
8880a708f8fSGustavo F. Padovan 
889b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
8900a708f8fSGustavo F. Padovan {
891c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
8920a708f8fSGustavo F. Padovan }
8930a708f8fSGustavo F. Padovan 
8949b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
8959b27f350SAndrei Emeltchenko {
8969b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
8979b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
8989b27f350SAndrei Emeltchenko 
8999b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9009b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9019b27f350SAndrei Emeltchenko 
9029b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9039b27f350SAndrei Emeltchenko 
9049b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9059b27f350SAndrei Emeltchenko 
9069b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9079b27f350SAndrei Emeltchenko }
9089b27f350SAndrei Emeltchenko 
9099f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9109f0caeb1SVinicius Costa Gomes {
9119f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9129f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9139f0caeb1SVinicius Costa Gomes 
9149f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9159f0caeb1SVinicius Costa Gomes 
9169f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9179f0caeb1SVinicius Costa Gomes 
9189f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9199f0caeb1SVinicius Costa Gomes 
9209f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9219f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9229f0caeb1SVinicius Costa Gomes 
9239f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9249f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9259f0caeb1SVinicius Costa Gomes 
9269f0caeb1SVinicius Costa Gomes 	if (parent)
9279f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9289f0caeb1SVinicius Costa Gomes 
9299f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9309f0caeb1SVinicius Costa Gomes }
9319f0caeb1SVinicius Costa Gomes 
932fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9330a708f8fSGustavo F. Padovan {
9348c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9350a708f8fSGustavo F. Padovan 
9369f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9379f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9389f0caeb1SVinicius Costa Gomes 		return;
9399f0caeb1SVinicius Costa Gomes 	}
9409f0caeb1SVinicius Costa Gomes 
9410a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9420a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9430a708f8fSGustavo F. Padovan 			return;
9440a708f8fSGustavo F. Padovan 
945d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9469b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9479b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9480a708f8fSGustavo F. Padovan 	} else {
9490a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
9500a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
9510a708f8fSGustavo F. Padovan 
9520a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9530a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
9540a708f8fSGustavo F. Padovan 
955ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
9560a708f8fSGustavo F. Padovan 
9570a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
9580a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
9590a708f8fSGustavo F. Padovan 	}
9600a708f8fSGustavo F. Padovan }
9610a708f8fSGustavo F. Padovan 
9620a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
9630a708f8fSGustavo F. Padovan {
9640a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
9650a708f8fSGustavo F. Padovan 	if (!disable_ertm)
9660a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
9670a708f8fSGustavo F. Padovan 
9680a708f8fSGustavo F. Padovan 	switch (mode) {
9690a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
9700a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
9710a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
9720a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
9730a708f8fSGustavo F. Padovan 	default:
9740a708f8fSGustavo F. Padovan 		return 0x00;
9750a708f8fSGustavo F. Padovan 	}
9760a708f8fSGustavo F. Padovan }
9770a708f8fSGustavo F. Padovan 
9784519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
9790a708f8fSGustavo F. Padovan {
9806be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
9810a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
9820a708f8fSGustavo F. Padovan 
9830a708f8fSGustavo F. Padovan 	if (!conn)
9840a708f8fSGustavo F. Padovan 		return;
9850a708f8fSGustavo F. Padovan 
9860c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
9871a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
9881a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
9891a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
9900a708f8fSGustavo F. Padovan 	}
9910a708f8fSGustavo F. Padovan 
992fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
993fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
9940a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
9950a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
9960a708f8fSGustavo F. Padovan 
9976be36555SAndrei Emeltchenko 	lock_sock(sk);
9980e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
9992e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10006be36555SAndrei Emeltchenko 	release_sock(sk);
10010a708f8fSGustavo F. Padovan }
10020a708f8fSGustavo F. Padovan 
10030a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10040a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10050a708f8fSGustavo F. Padovan {
10063df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10070a708f8fSGustavo F. Padovan 
10080a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10090a708f8fSGustavo F. Padovan 
10103df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10110a708f8fSGustavo F. Padovan 
10123df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
101348454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1014baa7e1faSGustavo F. Padovan 
10156be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10160a708f8fSGustavo F. Padovan 
1017715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10186be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10190a708f8fSGustavo F. Padovan 			continue;
10200a708f8fSGustavo F. Padovan 		}
10210a708f8fSGustavo F. Padovan 
102289bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1023d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1024b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10256be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10260a708f8fSGustavo F. Padovan 				continue;
10270a708f8fSGustavo F. Padovan 			}
10280a708f8fSGustavo F. Padovan 
1029c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1030c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1031c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10320f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10336be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10340a708f8fSGustavo F. Padovan 				continue;
10350a708f8fSGustavo F. Padovan 			}
10360a708f8fSGustavo F. Padovan 
10379b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10380a708f8fSGustavo F. Padovan 
103989bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10400a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10410a708f8fSGustavo F. Padovan 			char buf[128];
1042fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1043fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10440a708f8fSGustavo F. Padovan 
1045d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10466be36555SAndrei Emeltchenko 				lock_sock(sk);
10470a708f8fSGustavo F. Padovan 				if (bt_sk(sk)->defer_setup) {
10480a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
10490a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10500a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
105105e9a2f6SIlia Kolomisnky 					if (parent)
10520a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
10530a708f8fSGustavo F. Padovan 
10540a708f8fSGustavo F. Padovan 				} else {
10550e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
10560a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
10570a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
10580a708f8fSGustavo F. Padovan 				}
10596be36555SAndrei Emeltchenko 				release_sock(sk);
10600a708f8fSGustavo F. Padovan 			} else {
10610a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
10620a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
10630a708f8fSGustavo F. Padovan 			}
10640a708f8fSGustavo F. Padovan 
1065fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1066fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
10670a708f8fSGustavo F. Padovan 
1068c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
10690a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
10706be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10710a708f8fSGustavo F. Padovan 				continue;
10720a708f8fSGustavo F. Padovan 			}
10730a708f8fSGustavo F. Padovan 
1074c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
10750a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
107673ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
107773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
10780a708f8fSGustavo F. Padovan 		}
10790a708f8fSGustavo F. Padovan 
10806be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
10810a708f8fSGustavo F. Padovan 	}
10820a708f8fSGustavo F. Padovan 
10833df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
10840a708f8fSGustavo F. Padovan }
10850a708f8fSGustavo F. Padovan 
1086c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1087b62f328bSVille Tervo  * Returns closest match, locked.
1088b62f328bSVille Tervo  */
1089d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1090c2287681SIdo Yariv 						    bdaddr_t *src,
1091c2287681SIdo Yariv 						    bdaddr_t *dst)
1092b62f328bSVille Tervo {
109323691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1094b62f328bSVille Tervo 
109523691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1096b62f328bSVille Tervo 
109723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
109823691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1099fe4128e0SGustavo F. Padovan 
110089bc500eSGustavo F. Padovan 		if (state && c->state != state)
1101b62f328bSVille Tervo 			continue;
1102b62f328bSVille Tervo 
110323691d75SGustavo F. Padovan 		if (c->scid == cid) {
1104c2287681SIdo Yariv 			int src_match, dst_match;
1105c2287681SIdo Yariv 			int src_any, dst_any;
1106c2287681SIdo Yariv 
1107b62f328bSVille Tervo 			/* Exact match. */
1108c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1109c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1110c2287681SIdo Yariv 			if (src_match && dst_match) {
111123691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
111223691d75SGustavo F. Padovan 				return c;
111323691d75SGustavo F. Padovan 			}
1114b62f328bSVille Tervo 
1115b62f328bSVille Tervo 			/* Closest match */
1116c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1117c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1118c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1119c2287681SIdo Yariv 			    (src_any && dst_any))
112023691d75SGustavo F. Padovan 				c1 = c;
1121b62f328bSVille Tervo 		}
1122b62f328bSVille Tervo 	}
1123280f294fSGustavo F. Padovan 
112423691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1125b62f328bSVille Tervo 
112623691d75SGustavo F. Padovan 	return c1;
1127b62f328bSVille Tervo }
1128b62f328bSVille Tervo 
1129b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1130b62f328bSVille Tervo {
1131c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
113223691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1133b62f328bSVille Tervo 
1134b62f328bSVille Tervo 	BT_DBG("");
1135b62f328bSVille Tervo 
1136b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
113723691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1138c2287681SIdo Yariv 					  conn->src, conn->dst);
113923691d75SGustavo F. Padovan 	if (!pchan)
1140b62f328bSVille Tervo 		return;
1141b62f328bSVille Tervo 
114223691d75SGustavo F. Padovan 	parent = pchan->sk;
114323691d75SGustavo F. Padovan 
1144aa2ac881SGustavo F. Padovan 	lock_sock(parent);
114562f3a2cfSGustavo F. Padovan 
1146b62f328bSVille Tervo 	/* Check for backlog size */
1147b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1148b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1149b62f328bSVille Tervo 		goto clean;
1150b62f328bSVille Tervo 	}
1151b62f328bSVille Tervo 
115280808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
115380808e43SGustavo F. Padovan 	if (!chan)
1154b62f328bSVille Tervo 		goto clean;
1155b62f328bSVille Tervo 
115680808e43SGustavo F. Padovan 	sk = chan->sk;
11575d41ce1dSGustavo F. Padovan 
1158b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1159b62f328bSVille Tervo 
1160b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1161b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1162b62f328bSVille Tervo 
1163d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1164d1010240SGustavo F. Padovan 
11653d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
116648454079SGustavo F. Padovan 
1167c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1168b62f328bSVille Tervo 
11690e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1170b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1171b62f328bSVille Tervo 
1172b62f328bSVille Tervo clean:
1173aa2ac881SGustavo F. Padovan 	release_sock(parent);
1174b62f328bSVille Tervo }
1175b62f328bSVille Tervo 
11760a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
11770a708f8fSGustavo F. Padovan {
117848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
11790a708f8fSGustavo F. Padovan 
11800a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
11810a708f8fSGustavo F. Padovan 
1182b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1183b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1184b62f328bSVille Tervo 
1185160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1186160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1187160dc6acSVinicius Costa Gomes 
11883df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
11890a708f8fSGustavo F. Padovan 
11903df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1191baa7e1faSGustavo F. Padovan 
11926be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
11930a708f8fSGustavo F. Padovan 
119463128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1195b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1196cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1197acd7d370SVille Tervo 
119863128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
11996be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1200c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12016be36555SAndrei Emeltchenko 			lock_sock(sk);
12020e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12030a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12046be36555SAndrei Emeltchenko 			release_sock(sk);
1205b501d6a1SAnderson Briglia 
120689bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1207fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12080a708f8fSGustavo F. Padovan 
12096be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12100a708f8fSGustavo F. Padovan 	}
12110a708f8fSGustavo F. Padovan 
12123df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12130a708f8fSGustavo F. Padovan }
12140a708f8fSGustavo F. Padovan 
12150a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12160a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12170a708f8fSGustavo F. Padovan {
121848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12190a708f8fSGustavo F. Padovan 
12200a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12210a708f8fSGustavo F. Padovan 
12223df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12230a708f8fSGustavo F. Padovan 
12243df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1225ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12262e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12270a708f8fSGustavo F. Padovan 	}
12280a708f8fSGustavo F. Padovan 
12293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12300a708f8fSGustavo F. Padovan }
12310a708f8fSGustavo F. Padovan 
1232f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12330a708f8fSGustavo F. Padovan {
1234f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1235030013d8SGustavo F. Padovan 							info_timer.work);
12360a708f8fSGustavo F. Padovan 
12370a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12380a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12390a708f8fSGustavo F. Padovan 
12400a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12410a708f8fSGustavo F. Padovan }
12420a708f8fSGustavo F. Padovan 
12435d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12445d3de7dfSVinicius Costa Gomes {
12455d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12465d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12475d3de7dfSVinicius Costa Gomes 
12485d3de7dfSVinicius Costa Gomes 	if (!conn)
12495d3de7dfSVinicius Costa Gomes 		return;
12505d3de7dfSVinicius Costa Gomes 
12515d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12525d3de7dfSVinicius Costa Gomes 
12535d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
12545d3de7dfSVinicius Costa Gomes 
12553df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12563df91ea2SAndrei Emeltchenko 
12575d3de7dfSVinicius Costa Gomes 	/* Kill channels */
12585d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
1259*61d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
12606be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12616be36555SAndrei Emeltchenko 
12625d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
12636be36555SAndrei Emeltchenko 
12646be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12656be36555SAndrei Emeltchenko 
12665d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
1267*61d6ef3eSMat Martineau 		l2cap_chan_put(chan);
12685d3de7dfSVinicius Costa Gomes 	}
12695d3de7dfSVinicius Costa Gomes 
12703df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12713df91ea2SAndrei Emeltchenko 
127273d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
127373d80debSLuiz Augusto von Dentz 
12745d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1275127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
12765d3de7dfSVinicius Costa Gomes 
127751a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1278127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
12798aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1280d26a2345SVinicius Costa Gomes 	}
12815d3de7dfSVinicius Costa Gomes 
12825d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
12835d3de7dfSVinicius Costa Gomes 	kfree(conn);
12845d3de7dfSVinicius Costa Gomes }
12855d3de7dfSVinicius Costa Gomes 
12866c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
12875d3de7dfSVinicius Costa Gomes {
12886c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
12896c9d42a1SGustavo F. Padovan 						security_timer.work);
12905d3de7dfSVinicius Costa Gomes 
12915d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
12925d3de7dfSVinicius Costa Gomes }
12935d3de7dfSVinicius Costa Gomes 
12940a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
12950a708f8fSGustavo F. Padovan {
12960a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
129773d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
12980a708f8fSGustavo F. Padovan 
12990a708f8fSGustavo F. Padovan 	if (conn || status)
13000a708f8fSGustavo F. Padovan 		return conn;
13010a708f8fSGustavo F. Padovan 
130273d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
130373d80debSLuiz Augusto von Dentz 	if (!hchan)
13040a708f8fSGustavo F. Padovan 		return NULL;
13050a708f8fSGustavo F. Padovan 
130673d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
130773d80debSLuiz Augusto von Dentz 	if (!conn) {
130873d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
130973d80debSLuiz Augusto von Dentz 		return NULL;
131073d80debSLuiz Augusto von Dentz 	}
131173d80debSLuiz Augusto von Dentz 
13120a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13130a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
131473d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13150a708f8fSGustavo F. Padovan 
131673d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13170a708f8fSGustavo F. Padovan 
1318acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1319acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1320acd7d370SVille Tervo 	else
13210a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1322acd7d370SVille Tervo 
13230a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13240a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13250a708f8fSGustavo F. Padovan 
13260a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13270a708f8fSGustavo F. Padovan 
13280a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13293df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1330baa7e1faSGustavo F. Padovan 
1331baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13320a708f8fSGustavo F. Padovan 
13335d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13346c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13355d3de7dfSVinicius Costa Gomes 	else
1336030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13370a708f8fSGustavo F. Padovan 
13389f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13390a708f8fSGustavo F. Padovan 
13400a708f8fSGustavo F. Padovan 	return conn;
13410a708f8fSGustavo F. Padovan }
13420a708f8fSGustavo F. Padovan 
13430a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13440a708f8fSGustavo F. Padovan 
1345c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13460a708f8fSGustavo F. Padovan  * Returns closest match.
13470a708f8fSGustavo F. Padovan  */
1348c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1349c2287681SIdo Yariv 						   bdaddr_t *src,
1350c2287681SIdo Yariv 						   bdaddr_t *dst)
13510a708f8fSGustavo F. Padovan {
135223691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
13530a708f8fSGustavo F. Padovan 
135423691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
13550a708f8fSGustavo F. Padovan 
135623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
135723691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1358fe4128e0SGustavo F. Padovan 
135989bc500eSGustavo F. Padovan 		if (state && c->state != state)
13600a708f8fSGustavo F. Padovan 			continue;
13610a708f8fSGustavo F. Padovan 
136223691d75SGustavo F. Padovan 		if (c->psm == psm) {
1363c2287681SIdo Yariv 			int src_match, dst_match;
1364c2287681SIdo Yariv 			int src_any, dst_any;
1365c2287681SIdo Yariv 
13660a708f8fSGustavo F. Padovan 			/* Exact match. */
1367c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1368c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1369c2287681SIdo Yariv 			if (src_match && dst_match) {
1370a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
137123691d75SGustavo F. Padovan 				return c;
137223691d75SGustavo F. Padovan 			}
13730a708f8fSGustavo F. Padovan 
13740a708f8fSGustavo F. Padovan 			/* Closest match */
1375c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1376c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1377c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1378c2287681SIdo Yariv 			    (src_any && dst_any))
137923691d75SGustavo F. Padovan 				c1 = c;
13800a708f8fSGustavo F. Padovan 		}
13810a708f8fSGustavo F. Padovan 	}
13820a708f8fSGustavo F. Padovan 
138323691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
13840a708f8fSGustavo F. Padovan 
138523691d75SGustavo F. Padovan 	return c1;
13860a708f8fSGustavo F. Padovan }
13870a708f8fSGustavo F. Padovan 
13888e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
13898e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
13900a708f8fSGustavo F. Padovan {
13915d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
13920a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
13930a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
13940a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
13950a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
13960a708f8fSGustavo F. Padovan 	__u8 auth_type;
13970a708f8fSGustavo F. Padovan 	int err;
13980a708f8fSGustavo F. Padovan 
13998e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14008e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14010a708f8fSGustavo F. Padovan 
14020a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14030a708f8fSGustavo F. Padovan 	if (!hdev)
14040a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14050a708f8fSGustavo F. Padovan 
140609fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14070a708f8fSGustavo F. Padovan 
14086be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
140903a00194SGustavo F. Padovan 
141003a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
141103a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
141203a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
141303a00194SGustavo F. Padovan 		err = -EINVAL;
141403a00194SGustavo F. Padovan 		goto done;
141503a00194SGustavo F. Padovan 	}
141603a00194SGustavo F. Padovan 
141703a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
141803a00194SGustavo F. Padovan 		err = -EINVAL;
141903a00194SGustavo F. Padovan 		goto done;
142003a00194SGustavo F. Padovan 	}
142103a00194SGustavo F. Padovan 
142203a00194SGustavo F. Padovan 	switch (chan->mode) {
142303a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
142403a00194SGustavo F. Padovan 		break;
142503a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
142603a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
142703a00194SGustavo F. Padovan 		if (!disable_ertm)
142803a00194SGustavo F. Padovan 			break;
142903a00194SGustavo F. Padovan 		/* fall through */
143003a00194SGustavo F. Padovan 	default:
143103a00194SGustavo F. Padovan 		err = -ENOTSUPP;
143203a00194SGustavo F. Padovan 		goto done;
143303a00194SGustavo F. Padovan 	}
143403a00194SGustavo F. Padovan 
14356be36555SAndrei Emeltchenko 	lock_sock(sk);
14366be36555SAndrei Emeltchenko 
143703a00194SGustavo F. Padovan 	switch (sk->sk_state) {
143803a00194SGustavo F. Padovan 	case BT_CONNECT:
143903a00194SGustavo F. Padovan 	case BT_CONNECT2:
144003a00194SGustavo F. Padovan 	case BT_CONFIG:
144103a00194SGustavo F. Padovan 		/* Already connecting */
144203a00194SGustavo F. Padovan 		err = 0;
14436be36555SAndrei Emeltchenko 		release_sock(sk);
144403a00194SGustavo F. Padovan 		goto done;
144503a00194SGustavo F. Padovan 
144603a00194SGustavo F. Padovan 	case BT_CONNECTED:
144703a00194SGustavo F. Padovan 		/* Already connected */
144803a00194SGustavo F. Padovan 		err = -EISCONN;
14496be36555SAndrei Emeltchenko 		release_sock(sk);
145003a00194SGustavo F. Padovan 		goto done;
145103a00194SGustavo F. Padovan 
145203a00194SGustavo F. Padovan 	case BT_OPEN:
145303a00194SGustavo F. Padovan 	case BT_BOUND:
145403a00194SGustavo F. Padovan 		/* Can connect */
145503a00194SGustavo F. Padovan 		break;
145603a00194SGustavo F. Padovan 
145703a00194SGustavo F. Padovan 	default:
145803a00194SGustavo F. Padovan 		err = -EBADFD;
14596be36555SAndrei Emeltchenko 		release_sock(sk);
146003a00194SGustavo F. Padovan 		goto done;
146103a00194SGustavo F. Padovan 	}
146203a00194SGustavo F. Padovan 
146303a00194SGustavo F. Padovan 	/* Set destination address and psm */
14649219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
14656be36555SAndrei Emeltchenko 
14666be36555SAndrei Emeltchenko 	release_sock(sk);
14676be36555SAndrei Emeltchenko 
146803a00194SGustavo F. Padovan 	chan->psm = psm;
146903a00194SGustavo F. Padovan 	chan->dcid = cid;
14700a708f8fSGustavo F. Padovan 
14714343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
14720a708f8fSGustavo F. Padovan 
1473fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
14748e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
14754343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1476acd7d370SVille Tervo 	else
14778e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
14784343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1479acd7d370SVille Tervo 
148030e76272SVille Tervo 	if (IS_ERR(hcon)) {
148130e76272SVille Tervo 		err = PTR_ERR(hcon);
14820a708f8fSGustavo F. Padovan 		goto done;
148330e76272SVille Tervo 	}
14840a708f8fSGustavo F. Padovan 
14850a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
14860a708f8fSGustavo F. Padovan 	if (!conn) {
14870a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
148830e76272SVille Tervo 		err = -ENOMEM;
14890a708f8fSGustavo F. Padovan 		goto done;
14900a708f8fSGustavo F. Padovan 	}
14910a708f8fSGustavo F. Padovan 
14929f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
14939f0caeb1SVinicius Costa Gomes 		err = 0;
14949f0caeb1SVinicius Costa Gomes 
14959f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
14969f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
14979f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
14989f0caeb1SVinicius Costa Gomes 		}
14999f0caeb1SVinicius Costa Gomes 
15009f0caeb1SVinicius Costa Gomes 		if (err)
15019f0caeb1SVinicius Costa Gomes 			goto done;
15029f0caeb1SVinicius Costa Gomes 	}
15039f0caeb1SVinicius Costa Gomes 
15040a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15050a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15060a708f8fSGustavo F. Padovan 
15076be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
150848454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15096be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
151048454079SGustavo F. Padovan 
15116be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1512c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15130a708f8fSGustavo F. Padovan 
15140a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1515715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1516c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1517d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15186be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15190a708f8fSGustavo F. Padovan 		} else
1520fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15210a708f8fSGustavo F. Padovan 	}
15220a708f8fSGustavo F. Padovan 
152330e76272SVille Tervo 	err = 0;
152430e76272SVille Tervo 
15250a708f8fSGustavo F. Padovan done:
15266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
152709fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15280a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15290a708f8fSGustavo F. Padovan 	return err;
15300a708f8fSGustavo F. Padovan }
15310a708f8fSGustavo F. Padovan 
1532dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15330a708f8fSGustavo F. Padovan {
15348c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15350a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15360a708f8fSGustavo F. Padovan 	int err = 0;
15370a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15380a708f8fSGustavo F. Padovan 
15390a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15400a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1541a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15420a708f8fSGustavo F. Padovan 		if (!timeo)
15430a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15440a708f8fSGustavo F. Padovan 
15450a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15460a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15470a708f8fSGustavo F. Padovan 			break;
15480a708f8fSGustavo F. Padovan 		}
15490a708f8fSGustavo F. Padovan 
15500a708f8fSGustavo F. Padovan 		release_sock(sk);
15510a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15520a708f8fSGustavo F. Padovan 		lock_sock(sk);
1553a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
15540a708f8fSGustavo F. Padovan 
15550a708f8fSGustavo F. Padovan 		err = sock_error(sk);
15560a708f8fSGustavo F. Padovan 		if (err)
15570a708f8fSGustavo F. Padovan 			break;
15580a708f8fSGustavo F. Padovan 	}
15590a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
15600a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
15610a708f8fSGustavo F. Padovan 	return err;
15620a708f8fSGustavo F. Padovan }
15630a708f8fSGustavo F. Padovan 
1564721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
15650a708f8fSGustavo F. Padovan {
1566721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1567721c4181SGustavo F. Padovan 							monitor_timer.work);
15680a708f8fSGustavo F. Padovan 
1569525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
15700a708f8fSGustavo F. Padovan 
15716be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15726be36555SAndrei Emeltchenko 
15732c03a7a4SGustavo F. Padovan 	if (chan->retry_count >= chan->remote_max_tx) {
15748c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
15756be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15768d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
15770a708f8fSGustavo F. Padovan 		return;
15780a708f8fSGustavo F. Padovan 	}
15790a708f8fSGustavo F. Padovan 
15806a026610SGustavo F. Padovan 	chan->retry_count++;
15811a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15820a708f8fSGustavo F. Padovan 
1583525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
15846be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
15858d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
15860a708f8fSGustavo F. Padovan }
15870a708f8fSGustavo F. Padovan 
1588721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
15890a708f8fSGustavo F. Padovan {
1590721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1591721c4181SGustavo F. Padovan 							retrans_timer.work);
15920a708f8fSGustavo F. Padovan 
159349208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
15940a708f8fSGustavo F. Padovan 
15956be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
15966be36555SAndrei Emeltchenko 
15976a026610SGustavo F. Padovan 	chan->retry_count = 1;
15981a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
15990a708f8fSGustavo F. Padovan 
1600e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
16010a708f8fSGustavo F. Padovan 
1602525cd185SGustavo F. Padovan 	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
16036be36555SAndrei Emeltchenko 
16046be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16058d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16060a708f8fSGustavo F. Padovan }
16070a708f8fSGustavo F. Padovan 
160842e5c802SGustavo F. Padovan static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
16090a708f8fSGustavo F. Padovan {
16100a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16110a708f8fSGustavo F. Padovan 
161258d35f87SGustavo F. Padovan 	while ((skb = skb_peek(&chan->tx_q)) &&
16136a026610SGustavo F. Padovan 			chan->unacked_frames) {
16143ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq == chan->expected_ack_seq)
16150a708f8fSGustavo F. Padovan 			break;
16160a708f8fSGustavo F. Padovan 
161758d35f87SGustavo F. Padovan 		skb = skb_dequeue(&chan->tx_q);
16180a708f8fSGustavo F. Padovan 		kfree_skb(skb);
16190a708f8fSGustavo F. Padovan 
16206a026610SGustavo F. Padovan 		chan->unacked_frames--;
16210a708f8fSGustavo F. Padovan 	}
16220a708f8fSGustavo F. Padovan 
16236a026610SGustavo F. Padovan 	if (!chan->unacked_frames)
16241a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
16250a708f8fSGustavo F. Padovan }
16260a708f8fSGustavo F. Padovan 
162767c9e840SSzymon Janc static void l2cap_streaming_send(struct l2cap_chan *chan)
16280a708f8fSGustavo F. Padovan {
16290a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
163088843ab0SAndrei Emeltchenko 	u32 control;
163188843ab0SAndrei Emeltchenko 	u16 fcs;
16320a708f8fSGustavo F. Padovan 
163358d35f87SGustavo F. Padovan 	while ((skb = skb_dequeue(&chan->tx_q))) {
163488843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
1635fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
163688843ab0SAndrei Emeltchenko 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
16370a708f8fSGustavo F. Padovan 
163847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
163903a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
164003a51213SAndrei Emeltchenko 						skb->len - L2CAP_FCS_SIZE);
164103a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs,
164203a51213SAndrei Emeltchenko 					skb->data + skb->len - L2CAP_FCS_SIZE);
16430a708f8fSGustavo F. Padovan 		}
16440a708f8fSGustavo F. Padovan 
16454343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16460a708f8fSGustavo F. Padovan 
1647836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16480a708f8fSGustavo F. Padovan 	}
16490a708f8fSGustavo F. Padovan }
16500a708f8fSGustavo F. Padovan 
1651fb45de7dSAndrei Emeltchenko static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
16520a708f8fSGustavo F. Padovan {
16530a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
165488843ab0SAndrei Emeltchenko 	u16 fcs;
165588843ab0SAndrei Emeltchenko 	u32 control;
16560a708f8fSGustavo F. Padovan 
165758d35f87SGustavo F. Padovan 	skb = skb_peek(&chan->tx_q);
16580a708f8fSGustavo F. Padovan 	if (!skb)
16590a708f8fSGustavo F. Padovan 		return;
16600a708f8fSGustavo F. Padovan 
16613ce3514fSMat Martineau 	while (bt_cb(skb)->control.txseq != tx_seq) {
166258d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
16630a708f8fSGustavo F. Padovan 			return;
16640a708f8fSGustavo F. Padovan 
1665d1726b6dSSzymon Janc 		skb = skb_queue_next(&chan->tx_q, skb);
1666d1726b6dSSzymon Janc 	}
16670a708f8fSGustavo F. Padovan 
16683ce3514fSMat Martineau 	if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
16693ce3514fSMat Martineau 	    chan->remote_max_tx) {
16708c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
16710a708f8fSGustavo F. Padovan 		return;
16720a708f8fSGustavo F. Padovan 	}
16730a708f8fSGustavo F. Padovan 
16740a708f8fSGustavo F. Padovan 	tx_skb = skb_clone(skb, GFP_ATOMIC);
16753ce3514fSMat Martineau 	bt_cb(skb)->control.retries++;
167688843ab0SAndrei Emeltchenko 
167788843ab0SAndrei Emeltchenko 	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
16787e0ef6eeSAndrei Emeltchenko 	control &= __get_sar_mask(chan);
16790a708f8fSGustavo F. Padovan 
1680e2ab4353SGustavo F. Padovan 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
168103f6715dSAndrei Emeltchenko 		control |= __set_ctrl_final(chan);
16820a708f8fSGustavo F. Padovan 
16830b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
1684fb45de7dSAndrei Emeltchenko 	control |= __set_txseq(chan, tx_seq);
16850a708f8fSGustavo F. Padovan 
168688843ab0SAndrei Emeltchenko 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
16870a708f8fSGustavo F. Padovan 
168847d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
168903a51213SAndrei Emeltchenko 		fcs = crc16(0, (u8 *)tx_skb->data,
169003a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
169103a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs,
169203a51213SAndrei Emeltchenko 				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
16930a708f8fSGustavo F. Padovan 	}
16940a708f8fSGustavo F. Padovan 
16954343478fSGustavo F. Padovan 	l2cap_do_send(chan, tx_skb);
16960a708f8fSGustavo F. Padovan }
16970a708f8fSGustavo F. Padovan 
169867c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
16990a708f8fSGustavo F. Padovan {
17000a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
170188843ab0SAndrei Emeltchenko 	u16 fcs;
170288843ab0SAndrei Emeltchenko 	u32 control;
17030a708f8fSGustavo F. Padovan 	int nsent = 0;
17040a708f8fSGustavo F. Padovan 
170589bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17060a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17070a708f8fSGustavo F. Padovan 
170858d35f87SGustavo F. Padovan 	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
17090a708f8fSGustavo F. Padovan 
17103ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == chan->remote_max_tx &&
17113ce3514fSMat Martineau 		    chan->remote_max_tx) {
17128c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
17130a708f8fSGustavo F. Padovan 			break;
17140a708f8fSGustavo F. Padovan 		}
17150a708f8fSGustavo F. Padovan 
17160a708f8fSGustavo F. Padovan 		tx_skb = skb_clone(skb, GFP_ATOMIC);
17170a708f8fSGustavo F. Padovan 
17183ce3514fSMat Martineau 		bt_cb(skb)->control.retries++;
17190a708f8fSGustavo F. Padovan 
172088843ab0SAndrei Emeltchenko 		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
17217e0ef6eeSAndrei Emeltchenko 		control &= __get_sar_mask(chan);
17220a708f8fSGustavo F. Padovan 
1723e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
172403f6715dSAndrei Emeltchenko 			control |= __set_ctrl_final(chan);
1725e2ab4353SGustavo F. Padovan 
17260b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->buffer_seq);
1727fb45de7dSAndrei Emeltchenko 		control |= __set_txseq(chan, chan->next_tx_seq);
17280a708f8fSGustavo F. Padovan 
172988843ab0SAndrei Emeltchenko 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
17300a708f8fSGustavo F. Padovan 
173147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
173203a51213SAndrei Emeltchenko 			fcs = crc16(0, (u8 *)skb->data,
173303a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
173403a51213SAndrei Emeltchenko 			put_unaligned_le16(fcs, skb->data +
173503a51213SAndrei Emeltchenko 						tx_skb->len - L2CAP_FCS_SIZE);
17360a708f8fSGustavo F. Padovan 		}
17370a708f8fSGustavo F. Padovan 
17384343478fSGustavo F. Padovan 		l2cap_do_send(chan, tx_skb);
17390a708f8fSGustavo F. Padovan 
17401a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17410a708f8fSGustavo F. Padovan 
17423ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = chan->next_tx_seq;
1743836be934SAndrei Emeltchenko 
1744836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17450a708f8fSGustavo F. Padovan 
17463ce3514fSMat Martineau 		if (bt_cb(skb)->control.retries == 1) {
17476a026610SGustavo F. Padovan 			chan->unacked_frames++;
1748930fa4aeSSzymon Janc 
1749930fa4aeSSzymon Janc 			if (!nsent++)
1750930fa4aeSSzymon Janc 				__clear_ack_timer(chan);
17518ed7a0aeSSzymon Janc 		}
175223e9fde2SSuraj Sumangala 
17536a026610SGustavo F. Padovan 		chan->frames_sent++;
17540a708f8fSGustavo F. Padovan 
175558d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
175658d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17570a708f8fSGustavo F. Padovan 		else
175858d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
17590a708f8fSGustavo F. Padovan 	}
17600a708f8fSGustavo F. Padovan 
17610a708f8fSGustavo F. Padovan 	return nsent;
17620a708f8fSGustavo F. Padovan }
17630a708f8fSGustavo F. Padovan 
1764525cd185SGustavo F. Padovan static int l2cap_retransmit_frames(struct l2cap_chan *chan)
17650a708f8fSGustavo F. Padovan {
17660a708f8fSGustavo F. Padovan 	int ret;
17670a708f8fSGustavo F. Padovan 
176858d35f87SGustavo F. Padovan 	if (!skb_queue_empty(&chan->tx_q))
176958d35f87SGustavo F. Padovan 		chan->tx_send_head = chan->tx_q.next;
17700a708f8fSGustavo F. Padovan 
177142e5c802SGustavo F. Padovan 	chan->next_tx_seq = chan->expected_ack_seq;
1772525cd185SGustavo F. Padovan 	ret = l2cap_ertm_send(chan);
17730a708f8fSGustavo F. Padovan 	return ret;
17740a708f8fSGustavo F. Padovan }
17750a708f8fSGustavo F. Padovan 
1776b17e73bbSSzymon Janc static void __l2cap_send_ack(struct l2cap_chan *chan)
17770a708f8fSGustavo F. Padovan {
177888843ab0SAndrei Emeltchenko 	u32 control = 0;
17790a708f8fSGustavo F. Padovan 
17800b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
17810a708f8fSGustavo F. Padovan 
1782e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
1783ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
1784e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1785525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
17860a708f8fSGustavo F. Padovan 		return;
17870a708f8fSGustavo F. Padovan 	}
17880a708f8fSGustavo F. Padovan 
1789525cd185SGustavo F. Padovan 	if (l2cap_ertm_send(chan) > 0)
17900a708f8fSGustavo F. Padovan 		return;
17910a708f8fSGustavo F. Padovan 
1792ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
1793525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
17940a708f8fSGustavo F. Padovan }
17950a708f8fSGustavo F. Padovan 
1796b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1797b17e73bbSSzymon Janc {
1798b17e73bbSSzymon Janc 	__clear_ack_timer(chan);
1799b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
1800b17e73bbSSzymon Janc }
1801b17e73bbSSzymon Janc 
1802525cd185SGustavo F. Padovan static void l2cap_send_srejtail(struct l2cap_chan *chan)
18030a708f8fSGustavo F. Padovan {
18040a708f8fSGustavo F. Padovan 	struct srej_list *tail;
180588843ab0SAndrei Emeltchenko 	u32 control;
18060a708f8fSGustavo F. Padovan 
1807ab784b73SAndrei Emeltchenko 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
180803f6715dSAndrei Emeltchenko 	control |= __set_ctrl_final(chan);
18090a708f8fSGustavo F. Padovan 
181039d5a3eeSGustavo F. Padovan 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
18110b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, tail->tx_seq);
18120a708f8fSGustavo F. Padovan 
1813525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
18140a708f8fSGustavo F. Padovan }
18150a708f8fSGustavo F. Padovan 
181604124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
181704124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
181804124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
18190a708f8fSGustavo F. Padovan {
18200952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
18210a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
182290338947SGustavo Padovan 	int sent = 0;
18230a708f8fSGustavo F. Padovan 
18240a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
18250a708f8fSGustavo F. Padovan 		return -EFAULT;
18260a708f8fSGustavo F. Padovan 
18270a708f8fSGustavo F. Padovan 	sent += count;
18280a708f8fSGustavo F. Padovan 	len  -= count;
18290a708f8fSGustavo F. Padovan 
18300a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
18310a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
18320a708f8fSGustavo F. Padovan 	while (len) {
18330a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
18340a708f8fSGustavo F. Padovan 
18352f7719ceSAndrei Emeltchenko 		*frag = chan->ops->alloc_skb(chan, count,
183690338947SGustavo Padovan 					     msg->msg_flags & MSG_DONTWAIT);
18372f7719ceSAndrei Emeltchenko 
183890338947SGustavo Padovan 		if (IS_ERR(*frag))
183990338947SGustavo Padovan 			return PTR_ERR(*frag);
18400a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
18410a708f8fSGustavo F. Padovan 			return -EFAULT;
18420a708f8fSGustavo F. Padovan 
18435e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
18445e59b791SLuiz Augusto von Dentz 
18450a708f8fSGustavo F. Padovan 		sent += count;
18460a708f8fSGustavo F. Padovan 		len  -= count;
18470a708f8fSGustavo F. Padovan 
18480a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
18490a708f8fSGustavo F. Padovan 	}
18500a708f8fSGustavo F. Padovan 
18510a708f8fSGustavo F. Padovan 	return sent;
18520a708f8fSGustavo F. Padovan }
18530a708f8fSGustavo F. Padovan 
18545e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
18555e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18565e59b791SLuiz Augusto von Dentz 						u32 priority)
18570a708f8fSGustavo F. Padovan {
18588c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18590a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
186003a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
18610a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18620a708f8fSGustavo F. Padovan 
18636d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
18640a708f8fSGustavo F. Padovan 
18650a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
18662f7719ceSAndrei Emeltchenko 
18672f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
186890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
186990338947SGustavo Padovan 	if (IS_ERR(skb))
187090338947SGustavo Padovan 		return skb;
18710a708f8fSGustavo F. Padovan 
18725e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
18735e59b791SLuiz Augusto von Dentz 
18740a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
18750a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1876fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
18770a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
1878097db76cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, 2));
18790a708f8fSGustavo F. Padovan 
18800952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
18810a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
18820a708f8fSGustavo F. Padovan 		kfree_skb(skb);
18830a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
18840a708f8fSGustavo F. Padovan 	}
18850a708f8fSGustavo F. Padovan 	return skb;
18860a708f8fSGustavo F. Padovan }
18870a708f8fSGustavo F. Padovan 
18885e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
18895e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
18905e59b791SLuiz Augusto von Dentz 						u32 priority)
18910a708f8fSGustavo F. Padovan {
18928c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
18930a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
18940a708f8fSGustavo F. Padovan 	int err, count, hlen = L2CAP_HDR_SIZE;
18950a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
18960a708f8fSGustavo F. Padovan 
18976d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
18980a708f8fSGustavo F. Padovan 
18990a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19002f7719ceSAndrei Emeltchenko 
19012f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
190290338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
190390338947SGustavo Padovan 	if (IS_ERR(skb))
190490338947SGustavo Padovan 		return skb;
19050a708f8fSGustavo F. Padovan 
19065e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19075e59b791SLuiz Augusto von Dentz 
19080a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19090a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1910fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19110a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
19120a708f8fSGustavo F. Padovan 
19130952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19140a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19150a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19160a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19170a708f8fSGustavo F. Padovan 	}
19180a708f8fSGustavo F. Padovan 	return skb;
19190a708f8fSGustavo F. Padovan }
19200a708f8fSGustavo F. Padovan 
1921ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
1922ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
192388843ab0SAndrei Emeltchenko 						u32 control, u16 sdulen)
19240a708f8fSGustavo F. Padovan {
19258c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19260a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
1927e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
19280a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19290a708f8fSGustavo F. Padovan 
19306d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
19310a708f8fSGustavo F. Padovan 
19320a708f8fSGustavo F. Padovan 	if (!conn)
19330a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
19340a708f8fSGustavo F. Padovan 
1935e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1936e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
1937e4ca6d98SAndrei Emeltchenko 	else
1938e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
1939e4ca6d98SAndrei Emeltchenko 
19400a708f8fSGustavo F. Padovan 	if (sdulen)
194103a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
19420a708f8fSGustavo F. Padovan 
194347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
194403a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
19450a708f8fSGustavo F. Padovan 
19460a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19472f7719ceSAndrei Emeltchenko 
19482f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
194990338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
195090338947SGustavo Padovan 	if (IS_ERR(skb))
195190338947SGustavo Padovan 		return skb;
19520a708f8fSGustavo F. Padovan 
19530a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19540a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1955fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
19560a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
195788843ab0SAndrei Emeltchenko 
195888843ab0SAndrei Emeltchenko 	__put_control(chan, control, skb_put(skb, __ctrl_size(chan)));
195988843ab0SAndrei Emeltchenko 
19600a708f8fSGustavo F. Padovan 	if (sdulen)
196103a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
19620a708f8fSGustavo F. Padovan 
19630952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19640a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19650a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19660a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19670a708f8fSGustavo F. Padovan 	}
19680a708f8fSGustavo F. Padovan 
196947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
197003a51213SAndrei Emeltchenko 		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
19710a708f8fSGustavo F. Padovan 
19723ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
19730a708f8fSGustavo F. Padovan 	return skb;
19740a708f8fSGustavo F. Padovan }
19750a708f8fSGustavo F. Padovan 
197667c9e840SSzymon Janc static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
19770a708f8fSGustavo F. Padovan {
19780a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
19790a708f8fSGustavo F. Padovan 	struct sk_buff_head sar_queue;
198088843ab0SAndrei Emeltchenko 	u32 control;
19810a708f8fSGustavo F. Padovan 	size_t size = 0;
19820a708f8fSGustavo F. Padovan 
19830a708f8fSGustavo F. Padovan 	skb_queue_head_init(&sar_queue);
19847e0ef6eeSAndrei Emeltchenko 	control = __set_ctrl_sar(chan, L2CAP_SAR_START);
198547d1ec61SGustavo F. Padovan 	skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
19860a708f8fSGustavo F. Padovan 	if (IS_ERR(skb))
19870a708f8fSGustavo F. Padovan 		return PTR_ERR(skb);
19880a708f8fSGustavo F. Padovan 
19890a708f8fSGustavo F. Padovan 	__skb_queue_tail(&sar_queue, skb);
19902c03a7a4SGustavo F. Padovan 	len -= chan->remote_mps;
19912c03a7a4SGustavo F. Padovan 	size += chan->remote_mps;
19920a708f8fSGustavo F. Padovan 
19930a708f8fSGustavo F. Padovan 	while (len > 0) {
19940a708f8fSGustavo F. Padovan 		size_t buflen;
19950a708f8fSGustavo F. Padovan 
19962c03a7a4SGustavo F. Padovan 		if (len > chan->remote_mps) {
19977e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
19982c03a7a4SGustavo F. Padovan 			buflen = chan->remote_mps;
19990a708f8fSGustavo F. Padovan 		} else {
20007e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_END);
20010a708f8fSGustavo F. Padovan 			buflen = len;
20020a708f8fSGustavo F. Padovan 		}
20030a708f8fSGustavo F. Padovan 
200447d1ec61SGustavo F. Padovan 		skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
20050a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
20060a708f8fSGustavo F. Padovan 			skb_queue_purge(&sar_queue);
20070a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
20080a708f8fSGustavo F. Padovan 		}
20090a708f8fSGustavo F. Padovan 
20100a708f8fSGustavo F. Padovan 		__skb_queue_tail(&sar_queue, skb);
20110a708f8fSGustavo F. Padovan 		len -= buflen;
20120a708f8fSGustavo F. Padovan 		size += buflen;
20130a708f8fSGustavo F. Padovan 	}
201458d35f87SGustavo F. Padovan 	skb_queue_splice_tail(&sar_queue, &chan->tx_q);
201558d35f87SGustavo F. Padovan 	if (chan->tx_send_head == NULL)
201658d35f87SGustavo F. Padovan 		chan->tx_send_head = sar_queue.next;
20170a708f8fSGustavo F. Padovan 
20180a708f8fSGustavo F. Padovan 	return size;
20190a708f8fSGustavo F. Padovan }
20200a708f8fSGustavo F. Padovan 
20215e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
20225e59b791SLuiz Augusto von Dentz 								u32 priority)
20239a91a04aSGustavo F. Padovan {
20249a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
202588843ab0SAndrei Emeltchenko 	u32 control;
20269a91a04aSGustavo F. Padovan 	int err;
20279a91a04aSGustavo F. Padovan 
20289a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2029715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
20305e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
20319a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20329a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20339a91a04aSGustavo F. Padovan 
20349a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20359a91a04aSGustavo F. Padovan 		return len;
20369a91a04aSGustavo F. Padovan 	}
20379a91a04aSGustavo F. Padovan 
20389a91a04aSGustavo F. Padovan 	switch (chan->mode) {
20399a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
20409a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
20419a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
20429a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
20439a91a04aSGustavo F. Padovan 
20449a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
20455e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
20469a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
20479a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
20489a91a04aSGustavo F. Padovan 
20499a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20509a91a04aSGustavo F. Padovan 		err = len;
20519a91a04aSGustavo F. Padovan 		break;
20529a91a04aSGustavo F. Padovan 
20539a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
20549a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
20559a91a04aSGustavo F. Padovan 		/* Entire SDU fits into one PDU */
20569a91a04aSGustavo F. Padovan 		if (len <= chan->remote_mps) {
20577e0ef6eeSAndrei Emeltchenko 			control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
20589a91a04aSGustavo F. Padovan 			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
20599a91a04aSGustavo F. Padovan 									0);
20609a91a04aSGustavo F. Padovan 			if (IS_ERR(skb))
20619a91a04aSGustavo F. Padovan 				return PTR_ERR(skb);
20629a91a04aSGustavo F. Padovan 
20639a91a04aSGustavo F. Padovan 			__skb_queue_tail(&chan->tx_q, skb);
20649a91a04aSGustavo F. Padovan 
20659a91a04aSGustavo F. Padovan 			if (chan->tx_send_head == NULL)
20669a91a04aSGustavo F. Padovan 				chan->tx_send_head = skb;
20679a91a04aSGustavo F. Padovan 
20689a91a04aSGustavo F. Padovan 		} else {
20699a91a04aSGustavo F. Padovan 			/* Segment SDU into multiples PDUs */
20709a91a04aSGustavo F. Padovan 			err = l2cap_sar_segment_sdu(chan, msg, len);
20719a91a04aSGustavo F. Padovan 			if (err < 0)
20729a91a04aSGustavo F. Padovan 				return err;
20739a91a04aSGustavo F. Padovan 		}
20749a91a04aSGustavo F. Padovan 
20759a91a04aSGustavo F. Padovan 		if (chan->mode == L2CAP_MODE_STREAMING) {
20769a91a04aSGustavo F. Padovan 			l2cap_streaming_send(chan);
20779a91a04aSGustavo F. Padovan 			err = len;
20789a91a04aSGustavo F. Padovan 			break;
20799a91a04aSGustavo F. Padovan 		}
20809a91a04aSGustavo F. Padovan 
2081e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
2082e2ab4353SGustavo F. Padovan 				test_bit(CONN_WAIT_F, &chan->conn_state)) {
20839a91a04aSGustavo F. Padovan 			err = len;
20849a91a04aSGustavo F. Padovan 			break;
20859a91a04aSGustavo F. Padovan 		}
20869a91a04aSGustavo F. Padovan 
20879a91a04aSGustavo F. Padovan 		err = l2cap_ertm_send(chan);
20889a91a04aSGustavo F. Padovan 		if (err >= 0)
20899a91a04aSGustavo F. Padovan 			err = len;
20909a91a04aSGustavo F. Padovan 
20919a91a04aSGustavo F. Padovan 		break;
20929a91a04aSGustavo F. Padovan 
20939a91a04aSGustavo F. Padovan 	default:
20949a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
20959a91a04aSGustavo F. Padovan 		err = -EBADFD;
20969a91a04aSGustavo F. Padovan 	}
20979a91a04aSGustavo F. Padovan 
20989a91a04aSGustavo F. Padovan 	return err;
20999a91a04aSGustavo F. Padovan }
21009a91a04aSGustavo F. Padovan 
21010a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
21020a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
21030a708f8fSGustavo F. Padovan {
21040a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
210548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
21060a708f8fSGustavo F. Padovan 
21070a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
21080a708f8fSGustavo F. Padovan 
21093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
21103d57dc68SGustavo F. Padovan 
21113df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
211248454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2113715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
21140a708f8fSGustavo F. Padovan 			continue;
21150a708f8fSGustavo F. Padovan 
21160a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
21170a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
21180a708f8fSGustavo F. Padovan 			continue;
21190a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
21200a708f8fSGustavo F. Padovan 		if (!nskb)
21210a708f8fSGustavo F. Padovan 			continue;
21220a708f8fSGustavo F. Padovan 
212323070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
21240a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
21250a708f8fSGustavo F. Padovan 	}
21263d57dc68SGustavo F. Padovan 
21273df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
21280a708f8fSGustavo F. Padovan }
21290a708f8fSGustavo F. Padovan 
21300a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
21310a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
21320a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
21330a708f8fSGustavo F. Padovan {
21340a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
21350a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
21360a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
21370a708f8fSGustavo F. Padovan 	int len, count;
21380a708f8fSGustavo F. Padovan 
21390a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
21400a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
21410a708f8fSGustavo F. Padovan 
21420a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
21430a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
21440a708f8fSGustavo F. Padovan 
21450a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
21460a708f8fSGustavo F. Padovan 	if (!skb)
21470a708f8fSGustavo F. Padovan 		return NULL;
21480a708f8fSGustavo F. Padovan 
21490a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
21500a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
21513300d9a9SClaudio Takahasi 
21523300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
21533300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
21543300d9a9SClaudio Takahasi 	else
21550a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
21560a708f8fSGustavo F. Padovan 
21570a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
21580a708f8fSGustavo F. Padovan 	cmd->code  = code;
21590a708f8fSGustavo F. Padovan 	cmd->ident = ident;
21600a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
21610a708f8fSGustavo F. Padovan 
21620a708f8fSGustavo F. Padovan 	if (dlen) {
21630a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
21640a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
21650a708f8fSGustavo F. Padovan 		data += count;
21660a708f8fSGustavo F. Padovan 	}
21670a708f8fSGustavo F. Padovan 
21680a708f8fSGustavo F. Padovan 	len -= skb->len;
21690a708f8fSGustavo F. Padovan 
21700a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
21710a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
21720a708f8fSGustavo F. Padovan 	while (len) {
21730a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
21740a708f8fSGustavo F. Padovan 
21750a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
21760a708f8fSGustavo F. Padovan 		if (!*frag)
21770a708f8fSGustavo F. Padovan 			goto fail;
21780a708f8fSGustavo F. Padovan 
21790a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
21800a708f8fSGustavo F. Padovan 
21810a708f8fSGustavo F. Padovan 		len  -= count;
21820a708f8fSGustavo F. Padovan 		data += count;
21830a708f8fSGustavo F. Padovan 
21840a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
21850a708f8fSGustavo F. Padovan 	}
21860a708f8fSGustavo F. Padovan 
21870a708f8fSGustavo F. Padovan 	return skb;
21880a708f8fSGustavo F. Padovan 
21890a708f8fSGustavo F. Padovan fail:
21900a708f8fSGustavo F. Padovan 	kfree_skb(skb);
21910a708f8fSGustavo F. Padovan 	return NULL;
21920a708f8fSGustavo F. Padovan }
21930a708f8fSGustavo F. Padovan 
21940a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
21950a708f8fSGustavo F. Padovan {
21960a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
21970a708f8fSGustavo F. Padovan 	int len;
21980a708f8fSGustavo F. Padovan 
21990a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
22000a708f8fSGustavo F. Padovan 	*ptr += len;
22010a708f8fSGustavo F. Padovan 
22020a708f8fSGustavo F. Padovan 	*type = opt->type;
22030a708f8fSGustavo F. Padovan 	*olen = opt->len;
22040a708f8fSGustavo F. Padovan 
22050a708f8fSGustavo F. Padovan 	switch (opt->len) {
22060a708f8fSGustavo F. Padovan 	case 1:
22070a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
22080a708f8fSGustavo F. Padovan 		break;
22090a708f8fSGustavo F. Padovan 
22100a708f8fSGustavo F. Padovan 	case 2:
22110a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
22120a708f8fSGustavo F. Padovan 		break;
22130a708f8fSGustavo F. Padovan 
22140a708f8fSGustavo F. Padovan 	case 4:
22150a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
22160a708f8fSGustavo F. Padovan 		break;
22170a708f8fSGustavo F. Padovan 
22180a708f8fSGustavo F. Padovan 	default:
22190a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
22200a708f8fSGustavo F. Padovan 		break;
22210a708f8fSGustavo F. Padovan 	}
22220a708f8fSGustavo F. Padovan 
22230a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
22240a708f8fSGustavo F. Padovan 	return len;
22250a708f8fSGustavo F. Padovan }
22260a708f8fSGustavo F. Padovan 
22270a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
22280a708f8fSGustavo F. Padovan {
22290a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
22300a708f8fSGustavo F. Padovan 
22310a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
22320a708f8fSGustavo F. Padovan 
22330a708f8fSGustavo F. Padovan 	opt->type = type;
22340a708f8fSGustavo F. Padovan 	opt->len  = len;
22350a708f8fSGustavo F. Padovan 
22360a708f8fSGustavo F. Padovan 	switch (len) {
22370a708f8fSGustavo F. Padovan 	case 1:
22380a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
22390a708f8fSGustavo F. Padovan 		break;
22400a708f8fSGustavo F. Padovan 
22410a708f8fSGustavo F. Padovan 	case 2:
22420a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
22430a708f8fSGustavo F. Padovan 		break;
22440a708f8fSGustavo F. Padovan 
22450a708f8fSGustavo F. Padovan 	case 4:
22460a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
22470a708f8fSGustavo F. Padovan 		break;
22480a708f8fSGustavo F. Padovan 
22490a708f8fSGustavo F. Padovan 	default:
22500a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
22510a708f8fSGustavo F. Padovan 		break;
22520a708f8fSGustavo F. Padovan 	}
22530a708f8fSGustavo F. Padovan 
22540a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
22550a708f8fSGustavo F. Padovan }
22560a708f8fSGustavo F. Padovan 
2257f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2258f89cef09SAndrei Emeltchenko {
2259f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2260f89cef09SAndrei Emeltchenko 
2261f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2262f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2263f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2264f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2265f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2266f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2267f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2268f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2269f89cef09SAndrei Emeltchenko 		break;
2270f89cef09SAndrei Emeltchenko 
2271f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2272f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2273f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2274f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2275f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2276f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2277f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2278f89cef09SAndrei Emeltchenko 		break;
2279f89cef09SAndrei Emeltchenko 
2280f89cef09SAndrei Emeltchenko 	default:
2281f89cef09SAndrei Emeltchenko 		return;
2282f89cef09SAndrei Emeltchenko 	}
2283f89cef09SAndrei Emeltchenko 
2284f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2285f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2286f89cef09SAndrei Emeltchenko }
2287f89cef09SAndrei Emeltchenko 
2288721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
22890a708f8fSGustavo F. Padovan {
2290721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2291721c4181SGustavo F. Padovan 							ack_timer.work);
22920a708f8fSGustavo F. Padovan 
22932fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
22942fb9b3d4SGustavo F. Padovan 
22956be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
22966be36555SAndrei Emeltchenko 
2297b17e73bbSSzymon Janc 	__l2cap_send_ack(chan);
22986be36555SAndrei Emeltchenko 
22996be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
230009bfb2eeSSzymon Janc 
230109bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
23020a708f8fSGustavo F. Padovan }
23030a708f8fSGustavo F. Padovan 
23043c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
23050a708f8fSGustavo F. Padovan {
23063c588192SMat Martineau 	int err;
23073c588192SMat Martineau 
2308105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2309105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
231042e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
23116a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
231242e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
23136a026610SGustavo F. Padovan 	chan->num_acked = 0;
23146a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2315105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2316105bdf9eSMat Martineau 	chan->sdu = NULL;
2317105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2318105bdf9eSMat Martineau 	chan->sdu_len = 0;
2319105bdf9eSMat Martineau 
2320105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2321105bdf9eSMat Martineau 		return 0;
2322105bdf9eSMat Martineau 
2323105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2324105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
23250a708f8fSGustavo F. Padovan 
2326721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2327721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2328721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
23290a708f8fSGustavo F. Padovan 
2330f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
2331105bdf9eSMat Martineau 	skb_queue_head_init(&chan->tx_q);
23320a708f8fSGustavo F. Padovan 
233339d5a3eeSGustavo F. Padovan 	INIT_LIST_HEAD(&chan->srej_l);
23343c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
23353c588192SMat Martineau 	if (err < 0)
23363c588192SMat Martineau 		return err;
23373c588192SMat Martineau 
23383c588192SMat Martineau 	return l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
23390a708f8fSGustavo F. Padovan }
23400a708f8fSGustavo F. Padovan 
23410a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
23420a708f8fSGustavo F. Padovan {
23430a708f8fSGustavo F. Padovan 	switch (mode) {
23440a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
23460a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
23470a708f8fSGustavo F. Padovan 			return mode;
23480a708f8fSGustavo F. Padovan 		/* fall through */
23490a708f8fSGustavo F. Padovan 	default:
23500a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
23510a708f8fSGustavo F. Padovan 	}
23520a708f8fSGustavo F. Padovan }
23530a708f8fSGustavo F. Padovan 
23546327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
23556327eb98SAndrei Emeltchenko {
23566327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
23576327eb98SAndrei Emeltchenko }
23586327eb98SAndrei Emeltchenko 
2359f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2360f89cef09SAndrei Emeltchenko {
2361f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2362f89cef09SAndrei Emeltchenko }
2363f89cef09SAndrei Emeltchenko 
23646327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
23656327eb98SAndrei Emeltchenko {
23666327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2367836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
23686327eb98SAndrei Emeltchenko 		/* use extended control field */
23696327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2370836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2371836be934SAndrei Emeltchenko 	} else {
23726327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
23736327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2374836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2375836be934SAndrei Emeltchenko 	}
23766327eb98SAndrei Emeltchenko }
23776327eb98SAndrei Emeltchenko 
2378710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
23790a708f8fSGustavo F. Padovan {
23800a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
23810c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
23820a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2383c8f79162SAndrei Emeltchenko 	u16 size;
23840a708f8fSGustavo F. Padovan 
238549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
23860a708f8fSGustavo F. Padovan 
238773ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
23880a708f8fSGustavo F. Padovan 		goto done;
23890a708f8fSGustavo F. Padovan 
23900c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
23910a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
23920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2393c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
23940a708f8fSGustavo F. Padovan 			break;
23950a708f8fSGustavo F. Padovan 
2396f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2397f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2398f89cef09SAndrei Emeltchenko 
23990a708f8fSGustavo F. Padovan 		/* fall through */
24000a708f8fSGustavo F. Padovan 	default:
24018c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
24020a708f8fSGustavo F. Padovan 		break;
24030a708f8fSGustavo F. Padovan 	}
24040a708f8fSGustavo F. Padovan 
24050a708f8fSGustavo F. Padovan done:
24060c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
24070c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
24080a708f8fSGustavo F. Padovan 
24090c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
24100a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
24118c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
24128c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
24130a708f8fSGustavo F. Padovan 			break;
24140a708f8fSGustavo F. Padovan 
24150a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
24160a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
24170a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
24180a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24190a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
24200a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
24210a708f8fSGustavo F. Padovan 
24220a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24230a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24240a708f8fSGustavo F. Padovan 		break;
24250a708f8fSGustavo F. Padovan 
24260a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
24270a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
242847d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
24290a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24300a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2431c8f79162SAndrei Emeltchenko 
2432c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2433c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2434c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2435c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2436c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
24370a708f8fSGustavo F. Padovan 
24386327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
24396327eb98SAndrei Emeltchenko 
24406327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
24416327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
24420a708f8fSGustavo F. Padovan 
24430a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24440a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24450a708f8fSGustavo F. Padovan 
2446f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2447f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2448f89cef09SAndrei Emeltchenko 
24498c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
24500a708f8fSGustavo F. Padovan 			break;
24510a708f8fSGustavo F. Padovan 
245247d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2453c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
245447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
245547d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
24560a708f8fSGustavo F. Padovan 		}
24576327eb98SAndrei Emeltchenko 
24586327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
24596327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
24606327eb98SAndrei Emeltchenko 								chan->tx_win);
24610a708f8fSGustavo F. Padovan 		break;
24620a708f8fSGustavo F. Padovan 
24630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
24640a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
24650a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
24660a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
24670a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
24680a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2469c8f79162SAndrei Emeltchenko 
2470c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2471c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2472c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2473c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2474c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
24750a708f8fSGustavo F. Padovan 
24760a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
24770a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
24780a708f8fSGustavo F. Padovan 
2479f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2480f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2481f89cef09SAndrei Emeltchenko 
24828c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
24830a708f8fSGustavo F. Padovan 			break;
24840a708f8fSGustavo F. Padovan 
248547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2486c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
248747d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
248847d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
24890a708f8fSGustavo F. Padovan 		}
24900a708f8fSGustavo F. Padovan 		break;
24910a708f8fSGustavo F. Padovan 	}
24920a708f8fSGustavo F. Padovan 
2493fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
24940a708f8fSGustavo F. Padovan 	req->flags = cpu_to_le16(0);
24950a708f8fSGustavo F. Padovan 
24960a708f8fSGustavo F. Padovan 	return ptr - data;
24970a708f8fSGustavo F. Padovan }
24980a708f8fSGustavo F. Padovan 
249973ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
25000a708f8fSGustavo F. Padovan {
25010a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
25020a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
250373ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
250473ffa904SGustavo F. Padovan 	int len = chan->conf_len;
25050a708f8fSGustavo F. Padovan 	int type, hint, olen;
25060a708f8fSGustavo F. Padovan 	unsigned long val;
25070a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
250842dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
250942dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
25100a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
25110a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2512c8f79162SAndrei Emeltchenko 	u16 size;
25130a708f8fSGustavo F. Padovan 
251473ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
25150a708f8fSGustavo F. Padovan 
25160a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
25170a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
25180a708f8fSGustavo F. Padovan 
25190a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
25200a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
25210a708f8fSGustavo F. Padovan 
25220a708f8fSGustavo F. Padovan 		switch (type) {
25230a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
25240a708f8fSGustavo F. Padovan 			mtu = val;
25250a708f8fSGustavo F. Padovan 			break;
25260a708f8fSGustavo F. Padovan 
25270a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
25280c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
25290a708f8fSGustavo F. Padovan 			break;
25300a708f8fSGustavo F. Padovan 
25310a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
25320a708f8fSGustavo F. Padovan 			break;
25330a708f8fSGustavo F. Padovan 
25340a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
25350a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
25360a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
25370a708f8fSGustavo F. Padovan 			break;
25380a708f8fSGustavo F. Padovan 
25390a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
25400a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2541c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
254242dceae2SAndrei Emeltchenko 			break;
25430a708f8fSGustavo F. Padovan 
254442dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
254542dceae2SAndrei Emeltchenko 			remote_efs = 1;
254642dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
254742dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
25480a708f8fSGustavo F. Padovan 			break;
25490a708f8fSGustavo F. Padovan 
25506327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
25516327eb98SAndrei Emeltchenko 			if (!enable_hs)
25526327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
25536327eb98SAndrei Emeltchenko 
25546327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
25556327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2556836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
25576327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
25580a708f8fSGustavo F. Padovan 			break;
25590a708f8fSGustavo F. Padovan 
25600a708f8fSGustavo F. Padovan 		default:
25610a708f8fSGustavo F. Padovan 			if (hint)
25620a708f8fSGustavo F. Padovan 				break;
25630a708f8fSGustavo F. Padovan 
25640a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
25650a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
25660a708f8fSGustavo F. Padovan 			break;
25670a708f8fSGustavo F. Padovan 		}
25680a708f8fSGustavo F. Padovan 	}
25690a708f8fSGustavo F. Padovan 
257073ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
25710a708f8fSGustavo F. Padovan 		goto done;
25720a708f8fSGustavo F. Padovan 
25730c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
25740a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
25750a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2576c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
25770c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
25788c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
25790a708f8fSGustavo F. Padovan 			break;
25800a708f8fSGustavo F. Padovan 		}
25810a708f8fSGustavo F. Padovan 
258242dceae2SAndrei Emeltchenko 		if (remote_efs) {
258342dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
258442dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
258542dceae2SAndrei Emeltchenko 			else
258642dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
258742dceae2SAndrei Emeltchenko 		}
258842dceae2SAndrei Emeltchenko 
25890c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
25900a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
25910a708f8fSGustavo F. Padovan 
25920a708f8fSGustavo F. Padovan 		break;
25930a708f8fSGustavo F. Padovan 	}
25940a708f8fSGustavo F. Padovan 
25950a708f8fSGustavo F. Padovan done:
25960c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
25970a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
25980c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
25990a708f8fSGustavo F. Padovan 
260073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
26010a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
26020a708f8fSGustavo F. Padovan 
26030a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26040a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26050a708f8fSGustavo F. Padovan 	}
26060a708f8fSGustavo F. Padovan 
26070a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
26080a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
26090a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
26100a708f8fSGustavo F. Padovan 
26110a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
26120a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
26130a708f8fSGustavo F. Padovan 		else {
26140c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
2615c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
26160a708f8fSGustavo F. Padovan 		}
26170c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
26180a708f8fSGustavo F. Padovan 
261942dceae2SAndrei Emeltchenko 		if (remote_efs) {
262042dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
262142dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
262242dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
262342dceae2SAndrei Emeltchenko 
262442dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
262542dceae2SAndrei Emeltchenko 
262642dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
262742dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
262842dceae2SAndrei Emeltchenko 
262942dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
263042dceae2SAndrei Emeltchenko 							sizeof(efs),
263142dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
26320e8b207eSAndrei Emeltchenko 			} else {
26333e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
26340e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
26350e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
263642dceae2SAndrei Emeltchenko 			}
263742dceae2SAndrei Emeltchenko 		}
263842dceae2SAndrei Emeltchenko 
26390a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
26400a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
264147d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
2642c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26430a708f8fSGustavo F. Padovan 			break;
26440a708f8fSGustavo F. Padovan 
26450a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
26466327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
26472c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
26486327eb98SAndrei Emeltchenko 			else
26496327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
26506327eb98SAndrei Emeltchenko 
26512c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
26520a708f8fSGustavo F. Padovan 
2653c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2654c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2655c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2656c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2657c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2658c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2659c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
26600a708f8fSGustavo F. Padovan 
26610a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
26624fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
26630a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
26644fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
26650a708f8fSGustavo F. Padovan 
2666c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26670a708f8fSGustavo F. Padovan 
26680a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26690a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26700a708f8fSGustavo F. Padovan 
267142dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
267242dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
267342dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
267442dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
267542dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
267642dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
267742dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
267842dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
267942dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
268042dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
268142dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
268242dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
268342dceae2SAndrei Emeltchenko 			}
26840a708f8fSGustavo F. Padovan 			break;
26850a708f8fSGustavo F. Padovan 
26860a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
2687c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
2688c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
2689c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2690c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2691c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2692c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
2693c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
26940a708f8fSGustavo F. Padovan 
2695c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
26960a708f8fSGustavo F. Padovan 
26970a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
26980a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
26990a708f8fSGustavo F. Padovan 
27000a708f8fSGustavo F. Padovan 			break;
27010a708f8fSGustavo F. Padovan 
27020a708f8fSGustavo F. Padovan 		default:
27030a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
27040a708f8fSGustavo F. Padovan 
27050a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
27060c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
27070a708f8fSGustavo F. Padovan 		}
27080a708f8fSGustavo F. Padovan 
27090a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
2710c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
27110a708f8fSGustavo F. Padovan 	}
2712fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
27130a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
27140a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(0x0000);
27150a708f8fSGustavo F. Padovan 
27160a708f8fSGustavo F. Padovan 	return ptr - data;
27170a708f8fSGustavo F. Padovan }
27180a708f8fSGustavo F. Padovan 
2719b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
27200a708f8fSGustavo F. Padovan {
27210a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
27220a708f8fSGustavo F. Padovan 	void *ptr = req->data;
27230a708f8fSGustavo F. Padovan 	int type, olen;
27240a708f8fSGustavo F. Padovan 	unsigned long val;
272536e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
272666af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
27270a708f8fSGustavo F. Padovan 
2728fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
27290a708f8fSGustavo F. Padovan 
27300a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
27310a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
27320a708f8fSGustavo F. Padovan 
27330a708f8fSGustavo F. Padovan 		switch (type) {
27340a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
27350a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
27360a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
27370c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
27380a708f8fSGustavo F. Padovan 			} else
27390c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
27400c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
27410a708f8fSGustavo F. Padovan 			break;
27420a708f8fSGustavo F. Padovan 
27430a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
27440c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
27450a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
27460c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
27470a708f8fSGustavo F. Padovan 			break;
27480a708f8fSGustavo F. Padovan 
27490a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
27500a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
27510a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
27520a708f8fSGustavo F. Padovan 
2753c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
27540c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
27550a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
27560a708f8fSGustavo F. Padovan 
275747d1ec61SGustavo F. Padovan 			chan->fcs = 0;
27580a708f8fSGustavo F. Padovan 
27590a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
27600a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
27610a708f8fSGustavo F. Padovan 			break;
27626327eb98SAndrei Emeltchenko 
27636327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
27646327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
27656327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
27663e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
27673e6b3b95SGustavo F. Padovan 							chan->tx_win);
27686327eb98SAndrei Emeltchenko 			break;
276966af7aafSAndrei Emeltchenko 
277066af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
277166af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
277266af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
277366af7aafSAndrei Emeltchenko 
277466af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
277566af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
277666af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
277766af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
277866af7aafSAndrei Emeltchenko 
277966af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
278066af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
278166af7aafSAndrei Emeltchenko 			break;
27820a708f8fSGustavo F. Padovan 		}
27830a708f8fSGustavo F. Padovan 	}
27840a708f8fSGustavo F. Padovan 
27850c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
27860a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
27870a708f8fSGustavo F. Padovan 
27880c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
27890a708f8fSGustavo F. Padovan 
27900e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
27910a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
27920a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
279347d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
279447d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
279547d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
279666af7aafSAndrei Emeltchenko 
279766af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
279866af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
279966af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
280066af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
280166af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
280266af7aafSAndrei Emeltchenko 				chan->local_flush_to =
280366af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
280466af7aafSAndrei Emeltchenko 			}
28050a708f8fSGustavo F. Padovan 			break;
280666af7aafSAndrei Emeltchenko 
28070a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
280847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28090a708f8fSGustavo F. Padovan 		}
28100a708f8fSGustavo F. Padovan 	}
28110a708f8fSGustavo F. Padovan 
2812fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
28130a708f8fSGustavo F. Padovan 	req->flags  = cpu_to_le16(0x0000);
28140a708f8fSGustavo F. Padovan 
28150a708f8fSGustavo F. Padovan 	return ptr - data;
28160a708f8fSGustavo F. Padovan }
28170a708f8fSGustavo F. Padovan 
2818fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
28190a708f8fSGustavo F. Padovan {
28200a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
28210a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
28220a708f8fSGustavo F. Padovan 
2823fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
28240a708f8fSGustavo F. Padovan 
2825fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
28260a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
28270a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
28280a708f8fSGustavo F. Padovan 
28290a708f8fSGustavo F. Padovan 	return ptr - data;
28300a708f8fSGustavo F. Padovan }
28310a708f8fSGustavo F. Padovan 
28328c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
2833710f9b0aSGustavo F. Padovan {
2834710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
28358c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
2836710f9b0aSGustavo F. Padovan 	u8 buf[128];
2837710f9b0aSGustavo F. Padovan 
2838fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
2839fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
2840710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
2841710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
2842710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
2843710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
2844710f9b0aSGustavo F. Padovan 
2845c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
2846710f9b0aSGustavo F. Padovan 		return;
2847710f9b0aSGustavo F. Padovan 
2848710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
2849710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
2850710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
2851710f9b0aSGustavo F. Padovan }
2852710f9b0aSGustavo F. Padovan 
285347d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
28540a708f8fSGustavo F. Padovan {
28550a708f8fSGustavo F. Padovan 	int type, olen;
28560a708f8fSGustavo F. Padovan 	unsigned long val;
28570a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
28580a708f8fSGustavo F. Padovan 
285947d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
28600a708f8fSGustavo F. Padovan 
28610c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
28620a708f8fSGustavo F. Padovan 		return;
28630a708f8fSGustavo F. Padovan 
28640a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
28650a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
28660a708f8fSGustavo F. Padovan 
28670a708f8fSGustavo F. Padovan 		switch (type) {
28680a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
28690a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
28700a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
28710a708f8fSGustavo F. Padovan 			goto done;
28720a708f8fSGustavo F. Padovan 		}
28730a708f8fSGustavo F. Padovan 	}
28740a708f8fSGustavo F. Padovan 
287536e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
287636e999a8SMat Martineau 	 * did not send an RFC option.
287736e999a8SMat Martineau 	 */
287836e999a8SMat Martineau 	rfc.mode = chan->mode;
287936e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
288036e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
288136e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
288236e999a8SMat Martineau 
288336e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
288436e999a8SMat Martineau 
28850a708f8fSGustavo F. Padovan done:
28860a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
28870a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
288847d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
288947d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
289047d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28910a708f8fSGustavo F. Padovan 		break;
28920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
289347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
28940a708f8fSGustavo F. Padovan 	}
28950a708f8fSGustavo F. Padovan }
28960a708f8fSGustavo F. Padovan 
28970a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
28980a708f8fSGustavo F. Padovan {
2899e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
29000a708f8fSGustavo F. Padovan 
2901e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
29020a708f8fSGustavo F. Padovan 		return 0;
29030a708f8fSGustavo F. Padovan 
29040a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
29050a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
290617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
29070a708f8fSGustavo F. Padovan 
29080a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
29090a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
29100a708f8fSGustavo F. Padovan 
29110a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
29120a708f8fSGustavo F. Padovan 	}
29130a708f8fSGustavo F. Padovan 
29140a708f8fSGustavo F. Padovan 	return 0;
29150a708f8fSGustavo F. Padovan }
29160a708f8fSGustavo F. Padovan 
29170a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
29180a708f8fSGustavo F. Padovan {
29190a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
29200a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
292123691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
29220a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
29230a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
29240a708f8fSGustavo F. Padovan 
29250a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
29260a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
29270a708f8fSGustavo F. Padovan 
2928097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
29290a708f8fSGustavo F. Padovan 
29300a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
2931c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
293223691d75SGustavo F. Padovan 	if (!pchan) {
29330a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
29340a708f8fSGustavo F. Padovan 		goto sendresp;
29350a708f8fSGustavo F. Padovan 	}
29360a708f8fSGustavo F. Padovan 
293723691d75SGustavo F. Padovan 	parent = pchan->sk;
293823691d75SGustavo F. Padovan 
29393df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
2940aa2ac881SGustavo F. Padovan 	lock_sock(parent);
29410a708f8fSGustavo F. Padovan 
29420a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
29430a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
29440a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
29459f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
29460a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
29470a708f8fSGustavo F. Padovan 		goto response;
29480a708f8fSGustavo F. Padovan 	}
29490a708f8fSGustavo F. Padovan 
29500a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
29510a708f8fSGustavo F. Padovan 
29520a708f8fSGustavo F. Padovan 	/* Check for backlog size */
29530a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
29540a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
29550a708f8fSGustavo F. Padovan 		goto response;
29560a708f8fSGustavo F. Padovan 	}
29570a708f8fSGustavo F. Padovan 
295880808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
295980808e43SGustavo F. Padovan 	if (!chan)
29600a708f8fSGustavo F. Padovan 		goto response;
29610a708f8fSGustavo F. Padovan 
296280808e43SGustavo F. Padovan 	sk = chan->sk;
296380808e43SGustavo F. Padovan 
29640a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
2965baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
29660a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
2967ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
29680a708f8fSGustavo F. Padovan 		goto response;
29690a708f8fSGustavo F. Padovan 	}
29700a708f8fSGustavo F. Padovan 
29710a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
29720a708f8fSGustavo F. Padovan 
29730a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
29740a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
2975fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
2976fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
29770a708f8fSGustavo F. Padovan 
2978d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
2979d1010240SGustavo F. Padovan 
29806be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
298148454079SGustavo F. Padovan 
2982fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
29830a708f8fSGustavo F. Padovan 
2984c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
29850a708f8fSGustavo F. Padovan 
2986fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
29870a708f8fSGustavo F. Padovan 
29880a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
2989d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
29900a708f8fSGustavo F. Padovan 			if (bt_sk(sk)->defer_setup) {
29910e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
29920a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
29930a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
29940a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
29950a708f8fSGustavo F. Padovan 			} else {
29960e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
29970a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
29980a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
29990a708f8fSGustavo F. Padovan 			}
30000a708f8fSGustavo F. Padovan 		} else {
30010e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
30020a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
30030a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
30040a708f8fSGustavo F. Padovan 		}
30050a708f8fSGustavo F. Padovan 	} else {
30060e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
30070a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
30080a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
30090a708f8fSGustavo F. Padovan 	}
30100a708f8fSGustavo F. Padovan 
30110a708f8fSGustavo F. Padovan response:
3012aa2ac881SGustavo F. Padovan 	release_sock(parent);
30133df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30140a708f8fSGustavo F. Padovan 
30150a708f8fSGustavo F. Padovan sendresp:
30160a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
30170a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
30180a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
30190a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
30200a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
30210a708f8fSGustavo F. Padovan 
30220a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
30230a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
30240a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
30250a708f8fSGustavo F. Padovan 
30260a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
30270a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
30280a708f8fSGustavo F. Padovan 
3029ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
30300a708f8fSGustavo F. Padovan 
30310a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
30320a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
30330a708f8fSGustavo F. Padovan 	}
30340a708f8fSGustavo F. Padovan 
3035c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
30360a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
30370a708f8fSGustavo F. Padovan 		u8 buf[128];
3038c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
30390a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
304073ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
304173ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30420a708f8fSGustavo F. Padovan 	}
30430a708f8fSGustavo F. Padovan 
30440a708f8fSGustavo F. Padovan 	return 0;
30450a708f8fSGustavo F. Padovan }
30460a708f8fSGustavo F. Padovan 
30470a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
30480a708f8fSGustavo F. Padovan {
30490a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
30500a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
305148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30520a708f8fSGustavo F. Padovan 	u8 req[128];
30533df91ea2SAndrei Emeltchenko 	int err;
30540a708f8fSGustavo F. Padovan 
30550a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
30560a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
30570a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
30580a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
30590a708f8fSGustavo F. Padovan 
30601b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
30611b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
30620a708f8fSGustavo F. Padovan 
30633df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30643df91ea2SAndrei Emeltchenko 
30650a708f8fSGustavo F. Padovan 	if (scid) {
30663df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
30673df91ea2SAndrei Emeltchenko 		if (!chan) {
30683df91ea2SAndrei Emeltchenko 			err = -EFAULT;
30693df91ea2SAndrei Emeltchenko 			goto unlock;
30703df91ea2SAndrei Emeltchenko 		}
30710a708f8fSGustavo F. Padovan 	} else {
30723df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
30733df91ea2SAndrei Emeltchenko 		if (!chan) {
30743df91ea2SAndrei Emeltchenko 			err = -EFAULT;
30753df91ea2SAndrei Emeltchenko 			goto unlock;
30763df91ea2SAndrei Emeltchenko 		}
30770a708f8fSGustavo F. Padovan 	}
30780a708f8fSGustavo F. Padovan 
30793df91ea2SAndrei Emeltchenko 	err = 0;
30803df91ea2SAndrei Emeltchenko 
30816be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
308248454079SGustavo F. Padovan 
30830a708f8fSGustavo F. Padovan 	switch (result) {
30840a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
308589bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3086fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3087fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3088c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
30890a708f8fSGustavo F. Padovan 
3090c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
30910a708f8fSGustavo F. Padovan 			break;
30920a708f8fSGustavo F. Padovan 
30930a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
309473ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
309573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
30960a708f8fSGustavo F. Padovan 		break;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3099c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
31000a708f8fSGustavo F. Padovan 		break;
31010a708f8fSGustavo F. Padovan 
31020a708f8fSGustavo F. Padovan 	default:
310348454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
31040a708f8fSGustavo F. Padovan 		break;
31050a708f8fSGustavo F. Padovan 	}
31060a708f8fSGustavo F. Padovan 
31076be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
31083df91ea2SAndrei Emeltchenko 
31093df91ea2SAndrei Emeltchenko unlock:
31103df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
31113df91ea2SAndrei Emeltchenko 
31123df91ea2SAndrei Emeltchenko 	return err;
31130a708f8fSGustavo F. Padovan }
31140a708f8fSGustavo F. Padovan 
311547d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
31160a708f8fSGustavo F. Padovan {
31170a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
31180a708f8fSGustavo F. Padovan 	 * sides request it.
31190a708f8fSGustavo F. Padovan 	 */
31200c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
312147d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3122c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
312347d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
31240a708f8fSGustavo F. Padovan }
31250a708f8fSGustavo F. Padovan 
31260a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
31270a708f8fSGustavo F. Padovan {
31280a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
31290a708f8fSGustavo F. Padovan 	u16 dcid, flags;
31300a708f8fSGustavo F. Padovan 	u8 rsp[64];
313148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
31323c588192SMat Martineau 	int len, err = 0;
31330a708f8fSGustavo F. Padovan 
31340a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
31350a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
31360a708f8fSGustavo F. Padovan 
31370a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
31380a708f8fSGustavo F. Padovan 
3139baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
314048454079SGustavo F. Padovan 	if (!chan)
31410a708f8fSGustavo F. Padovan 		return -ENOENT;
31420a708f8fSGustavo F. Padovan 
31436be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
314448454079SGustavo F. Padovan 
3145033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3146e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
31470a708f8fSGustavo F. Padovan 
3148e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3149e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3150e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3151e2fd318eSIlia Kolomisnky 
31520a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
31530a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
31540a708f8fSGustavo F. Padovan 		goto unlock;
31550a708f8fSGustavo F. Padovan 	}
31560a708f8fSGustavo F. Padovan 
31570a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
31580a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
31597ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
31600a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3161fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
31620a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
31630a708f8fSGustavo F. Padovan 		goto unlock;
31640a708f8fSGustavo F. Padovan 	}
31650a708f8fSGustavo F. Padovan 
31660a708f8fSGustavo F. Padovan 	/* Store config. */
316773ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
316873ffa904SGustavo F. Padovan 	chan->conf_len += len;
31690a708f8fSGustavo F. Padovan 
31700a708f8fSGustavo F. Padovan 	if (flags & 0x0001) {
31710a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
31720a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3173fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
31740a708f8fSGustavo F. Padovan 					L2CAP_CONF_SUCCESS, 0x0001), rsp);
31750a708f8fSGustavo F. Padovan 		goto unlock;
31760a708f8fSGustavo F. Padovan 	}
31770a708f8fSGustavo F. Padovan 
31780a708f8fSGustavo F. Padovan 	/* Complete config. */
317973ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
31800a708f8fSGustavo F. Padovan 	if (len < 0) {
3181e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
31820a708f8fSGustavo F. Padovan 		goto unlock;
31830a708f8fSGustavo F. Padovan 	}
31840a708f8fSGustavo F. Padovan 
31850a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
318673ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
31870a708f8fSGustavo F. Padovan 
31880a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
318973ffa904SGustavo F. Padovan 	chan->conf_len = 0;
31900a708f8fSGustavo F. Padovan 
3191c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
31920a708f8fSGustavo F. Padovan 		goto unlock;
31930a708f8fSGustavo F. Padovan 
3194c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
319547d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
31960a708f8fSGustavo F. Padovan 
319789bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
31980a708f8fSGustavo F. Padovan 
3199105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3200105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
32013c588192SMat Martineau 			err = l2cap_ertm_init(chan);
32020a708f8fSGustavo F. Padovan 
32033c588192SMat Martineau 		if (err < 0)
32043c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
32053c588192SMat Martineau 		else
3206cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
32073c588192SMat Martineau 
32080a708f8fSGustavo F. Padovan 		goto unlock;
32090a708f8fSGustavo F. Padovan 	}
32100a708f8fSGustavo F. Padovan 
3211c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
32120a708f8fSGustavo F. Padovan 		u8 buf[64];
32130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
321473ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
321573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
32160a708f8fSGustavo F. Padovan 	}
32170a708f8fSGustavo F. Padovan 
32180e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
32190e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
32200e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
32210e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
32220e8b207eSAndrei Emeltchenko 
32230e8b207eSAndrei Emeltchenko 		/* check compatibility */
32240e8b207eSAndrei Emeltchenko 
32250e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
32260e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
32270e8b207eSAndrei Emeltchenko 
32280e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
32290e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
32300e8b207eSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, 0x0000), rsp);
32310e8b207eSAndrei Emeltchenko 	}
32320e8b207eSAndrei Emeltchenko 
32330a708f8fSGustavo F. Padovan unlock:
32346be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
32353c588192SMat Martineau 	return err;
32360a708f8fSGustavo F. Padovan }
32370a708f8fSGustavo F. Padovan 
32380a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
32390a708f8fSGustavo F. Padovan {
32400a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
32410a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
324248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
324361386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
32443c588192SMat Martineau 	int err = 0;
32450a708f8fSGustavo F. Padovan 
32460a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
32470a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
32480a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
32490a708f8fSGustavo F. Padovan 
325061386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
325161386cbaSAndrei Emeltchenko 	       result, len);
32520a708f8fSGustavo F. Padovan 
3253baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
325448454079SGustavo F. Padovan 	if (!chan)
32550a708f8fSGustavo F. Padovan 		return 0;
32560a708f8fSGustavo F. Padovan 
32576be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
325848454079SGustavo F. Padovan 
32590a708f8fSGustavo F. Padovan 	switch (result) {
32600a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
326147d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
32620e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
32630a708f8fSGustavo F. Padovan 		break;
32640a708f8fSGustavo F. Padovan 
32650e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
32660e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
32670e8b207eSAndrei Emeltchenko 
32680e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
32690e8b207eSAndrei Emeltchenko 			char buf[64];
32700e8b207eSAndrei Emeltchenko 
32710e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
32720e8b207eSAndrei Emeltchenko 								buf, &result);
32730e8b207eSAndrei Emeltchenko 			if (len < 0) {
32740e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
32750e8b207eSAndrei Emeltchenko 				goto done;
32760e8b207eSAndrei Emeltchenko 			}
32770e8b207eSAndrei Emeltchenko 
32780e8b207eSAndrei Emeltchenko 			/* check compatibility */
32790e8b207eSAndrei Emeltchenko 
32800e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
32810e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
32820e8b207eSAndrei Emeltchenko 
32830e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
32840e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
32850e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
32860e8b207eSAndrei Emeltchenko 		}
32870e8b207eSAndrei Emeltchenko 		goto done;
32880e8b207eSAndrei Emeltchenko 
32890a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
329073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
32910a708f8fSGustavo F. Padovan 			char req[64];
32920a708f8fSGustavo F. Padovan 
32930a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3294e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
32950a708f8fSGustavo F. Padovan 				goto done;
32960a708f8fSGustavo F. Padovan 			}
32970a708f8fSGustavo F. Padovan 
32980a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
32990a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3300b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3301b4450035SGustavo F. Padovan 								req, &result);
33020a708f8fSGustavo F. Padovan 			if (len < 0) {
3303e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
33040a708f8fSGustavo F. Padovan 				goto done;
33050a708f8fSGustavo F. Padovan 			}
33060a708f8fSGustavo F. Padovan 
33070a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
33080a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
330973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
33100a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
33110a708f8fSGustavo F. Padovan 				goto done;
33120a708f8fSGustavo F. Padovan 			break;
33130a708f8fSGustavo F. Padovan 		}
33140a708f8fSGustavo F. Padovan 
33150a708f8fSGustavo F. Padovan 	default:
33166be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
33172e0052e4SAndrei Emeltchenko 
3318ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3319e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
33200a708f8fSGustavo F. Padovan 		goto done;
33210a708f8fSGustavo F. Padovan 	}
33220a708f8fSGustavo F. Padovan 
33230a708f8fSGustavo F. Padovan 	if (flags & 0x01)
33240a708f8fSGustavo F. Padovan 		goto done;
33250a708f8fSGustavo F. Padovan 
3326c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
33270a708f8fSGustavo F. Padovan 
3328c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
332947d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
33300a708f8fSGustavo F. Padovan 
333189bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3332105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3333105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
33343c588192SMat Martineau 			err = l2cap_ertm_init(chan);
33350a708f8fSGustavo F. Padovan 
33363c588192SMat Martineau 		if (err < 0)
33373c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
33383c588192SMat Martineau 		else
3339cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
33400a708f8fSGustavo F. Padovan 	}
33410a708f8fSGustavo F. Padovan 
33420a708f8fSGustavo F. Padovan done:
33436be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33443c588192SMat Martineau 	return err;
33450a708f8fSGustavo F. Padovan }
33460a708f8fSGustavo F. Padovan 
33470a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33480a708f8fSGustavo F. Padovan {
33490a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
33500a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
33510a708f8fSGustavo F. Padovan 	u16 dcid, scid;
335248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33530a708f8fSGustavo F. Padovan 	struct sock *sk;
33540a708f8fSGustavo F. Padovan 
33550a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
33560a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
33570a708f8fSGustavo F. Padovan 
33580a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
33590a708f8fSGustavo F. Padovan 
33603df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
33613df91ea2SAndrei Emeltchenko 
33623df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
33633df91ea2SAndrei Emeltchenko 	if (!chan) {
33643df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
33650a708f8fSGustavo F. Padovan 		return 0;
33663df91ea2SAndrei Emeltchenko 	}
33670a708f8fSGustavo F. Padovan 
33686be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
33696be36555SAndrei Emeltchenko 
337048454079SGustavo F. Padovan 	sk = chan->sk;
337148454079SGustavo F. Padovan 
3372fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3373fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
33740a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
33750a708f8fSGustavo F. Padovan 
33766be36555SAndrei Emeltchenko 	lock_sock(sk);
33770a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
33786be36555SAndrei Emeltchenko 	release_sock(sk);
33790a708f8fSGustavo F. Padovan 
3380*61d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
338148454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
33826be36555SAndrei Emeltchenko 
33836be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
33840a708f8fSGustavo F. Padovan 
3385ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3386*61d6ef3eSMat Martineau 	l2cap_chan_put(chan);
33873df91ea2SAndrei Emeltchenko 
33883df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
33893df91ea2SAndrei Emeltchenko 
33900a708f8fSGustavo F. Padovan 	return 0;
33910a708f8fSGustavo F. Padovan }
33920a708f8fSGustavo F. Padovan 
33930a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33940a708f8fSGustavo F. Padovan {
33950a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
33960a708f8fSGustavo F. Padovan 	u16 dcid, scid;
339748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
33980a708f8fSGustavo F. Padovan 
33990a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
34000a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
34010a708f8fSGustavo F. Padovan 
34020a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
34030a708f8fSGustavo F. Padovan 
34043df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34053df91ea2SAndrei Emeltchenko 
34063df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
34073df91ea2SAndrei Emeltchenko 	if (!chan) {
34083df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
34090a708f8fSGustavo F. Padovan 		return 0;
34103df91ea2SAndrei Emeltchenko 	}
34110a708f8fSGustavo F. Padovan 
34126be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
341348454079SGustavo F. Padovan 
3414*61d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
341548454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
34166be36555SAndrei Emeltchenko 
34176be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
34180a708f8fSGustavo F. Padovan 
3419ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3420*61d6ef3eSMat Martineau 	l2cap_chan_put(chan);
34213df91ea2SAndrei Emeltchenko 
34223df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34233df91ea2SAndrei Emeltchenko 
34240a708f8fSGustavo F. Padovan 	return 0;
34250a708f8fSGustavo F. Padovan }
34260a708f8fSGustavo F. Padovan 
34270a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34280a708f8fSGustavo F. Padovan {
34290a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
34300a708f8fSGustavo F. Padovan 	u16 type;
34310a708f8fSGustavo F. Padovan 
34320a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
34330a708f8fSGustavo F. Padovan 
34340a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
34350a708f8fSGustavo F. Padovan 
34360a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
34370a708f8fSGustavo F. Padovan 		u8 buf[8];
34380a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
34390a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
34400a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34410a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
34420a708f8fSGustavo F. Padovan 		if (!disable_ertm)
34430a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
34440a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3445a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
34466327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
34476327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3448a5fd6f30SAndrei Emeltchenko 
34490a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
34500a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34510a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
34520a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
34530a708f8fSGustavo F. Padovan 		u8 buf[12];
34540a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
345550a147cdSMat Martineau 
345650a147cdSMat Martineau 		if (enable_hs)
345750a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
345850a147cdSMat Martineau 		else
345950a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
346050a147cdSMat Martineau 
34610a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
34620a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3463c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
34640a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34650a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
34660a708f8fSGustavo F. Padovan 	} else {
34670a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
34680a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
34690a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
34700a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
34710a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
34720a708f8fSGustavo F. Padovan 	}
34730a708f8fSGustavo F. Padovan 
34740a708f8fSGustavo F. Padovan 	return 0;
34750a708f8fSGustavo F. Padovan }
34760a708f8fSGustavo F. Padovan 
34770a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34780a708f8fSGustavo F. Padovan {
34790a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
34800a708f8fSGustavo F. Padovan 	u16 type, result;
34810a708f8fSGustavo F. Padovan 
34820a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
34830a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
34840a708f8fSGustavo F. Padovan 
34850a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
34860a708f8fSGustavo F. Padovan 
3487e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3488e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3489e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3490e90165beSAndrei Emeltchenko 		return 0;
3491e90165beSAndrei Emeltchenko 
349217cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
34930a708f8fSGustavo F. Padovan 
34940a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
34950a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
34960a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
34970a708f8fSGustavo F. Padovan 
34980a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
34990a708f8fSGustavo F. Padovan 
35000a708f8fSGustavo F. Padovan 		return 0;
35010a708f8fSGustavo F. Padovan 	}
35020a708f8fSGustavo F. Padovan 
3503978c93b9SAndrei Emeltchenko 	switch (type) {
3504978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
35050a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
35060a708f8fSGustavo F. Padovan 
35070a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
35080a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
35090a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
35100a708f8fSGustavo F. Padovan 
35110a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
35120a708f8fSGustavo F. Padovan 
35130a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
35140a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
35150a708f8fSGustavo F. Padovan 		} else {
35160a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35170a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
35180a708f8fSGustavo F. Padovan 
35190a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
35200a708f8fSGustavo F. Padovan 		}
3521978c93b9SAndrei Emeltchenko 		break;
3522978c93b9SAndrei Emeltchenko 
3523978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3524978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
35250a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
35260a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
35270a708f8fSGustavo F. Padovan 
35280a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3529978c93b9SAndrei Emeltchenko 		break;
35300a708f8fSGustavo F. Padovan 	}
35310a708f8fSGustavo F. Padovan 
35320a708f8fSGustavo F. Padovan 	return 0;
35330a708f8fSGustavo F. Padovan }
35340a708f8fSGustavo F. Padovan 
3535f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3536f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3537f94ff6ffSMat Martineau 					void *data)
3538f94ff6ffSMat Martineau {
3539f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3540f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3541f94ff6ffSMat Martineau 	u16 psm, scid;
3542f94ff6ffSMat Martineau 
3543f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3544f94ff6ffSMat Martineau 		return -EPROTO;
3545f94ff6ffSMat Martineau 
3546f94ff6ffSMat Martineau 	if (!enable_hs)
3547f94ff6ffSMat Martineau 		return -EINVAL;
3548f94ff6ffSMat Martineau 
3549f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3550f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3551f94ff6ffSMat Martineau 
3552f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
3553f94ff6ffSMat Martineau 
3554f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3555f94ff6ffSMat Martineau 	rsp.dcid = 0;
3556f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
35578ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
35588ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3559f94ff6ffSMat Martineau 
3560f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3561f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3562f94ff6ffSMat Martineau 
3563f94ff6ffSMat Martineau 	return 0;
3564f94ff6ffSMat Martineau }
3565f94ff6ffSMat Martineau 
3566f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3567f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3568f94ff6ffSMat Martineau {
3569f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3570f94ff6ffSMat Martineau 
3571f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3572f94ff6ffSMat Martineau }
3573f94ff6ffSMat Martineau 
35748d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
35758d5a04a1SMat Martineau 							u16 icid, u16 result)
35768d5a04a1SMat Martineau {
35778d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
35788d5a04a1SMat Martineau 
35798d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
35808d5a04a1SMat Martineau 
35818d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
35828d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
35838d5a04a1SMat Martineau 
35848d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
35858d5a04a1SMat Martineau }
35868d5a04a1SMat Martineau 
35878d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
35888d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
35898d5a04a1SMat Martineau {
35908d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
35918d5a04a1SMat Martineau 	u8 ident;
35928d5a04a1SMat Martineau 
35938d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
35948d5a04a1SMat Martineau 
35958d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
35968d5a04a1SMat Martineau 	if (chan)
35978d5a04a1SMat Martineau 		chan->ident = ident;
35988d5a04a1SMat Martineau 
35998d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
36008d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
36018d5a04a1SMat Martineau 
36028d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
36038d5a04a1SMat Martineau }
36048d5a04a1SMat Martineau 
36058d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
36068d5a04a1SMat Martineau 								u16 icid)
36078d5a04a1SMat Martineau {
36088d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
36098d5a04a1SMat Martineau 
36108d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
36118d5a04a1SMat Martineau 
36128d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
36138d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
36148d5a04a1SMat Martineau }
36158d5a04a1SMat Martineau 
36168d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
36178d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36188d5a04a1SMat Martineau {
36198d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
36208d5a04a1SMat Martineau 	u16 icid = 0;
36218d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
36228d5a04a1SMat Martineau 
36238d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
36248d5a04a1SMat Martineau 		return -EPROTO;
36258d5a04a1SMat Martineau 
36268d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
36278d5a04a1SMat Martineau 
36288d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
36298d5a04a1SMat Martineau 
36308d5a04a1SMat Martineau 	if (!enable_hs)
36318d5a04a1SMat Martineau 		return -EINVAL;
36328d5a04a1SMat Martineau 
36338d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
36348d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
36358d5a04a1SMat Martineau 
36368d5a04a1SMat Martineau 	return 0;
36378d5a04a1SMat Martineau }
36388d5a04a1SMat Martineau 
36398d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
36408d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36418d5a04a1SMat Martineau {
36428d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
36438d5a04a1SMat Martineau 	u16 icid, result;
36448d5a04a1SMat Martineau 
36458d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36468d5a04a1SMat Martineau 		return -EPROTO;
36478d5a04a1SMat Martineau 
36488d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36498d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
36508d5a04a1SMat Martineau 
36518d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36528d5a04a1SMat Martineau 
36538d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
36548d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
36558d5a04a1SMat Martineau 
36568d5a04a1SMat Martineau 	return 0;
36578d5a04a1SMat Martineau }
36588d5a04a1SMat Martineau 
36598d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
36608d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36618d5a04a1SMat Martineau {
36628d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
36638d5a04a1SMat Martineau 	u16 icid, result;
36648d5a04a1SMat Martineau 
36658d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
36668d5a04a1SMat Martineau 		return -EPROTO;
36678d5a04a1SMat Martineau 
36688d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
36698d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
36708d5a04a1SMat Martineau 
36718d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
36728d5a04a1SMat Martineau 
36738d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
36748d5a04a1SMat Martineau 
36758d5a04a1SMat Martineau 	return 0;
36768d5a04a1SMat Martineau }
36778d5a04a1SMat Martineau 
36788d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
36798d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
36808d5a04a1SMat Martineau {
36818d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
36828d5a04a1SMat Martineau 	u16 icid;
36838d5a04a1SMat Martineau 
36848d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
36858d5a04a1SMat Martineau 		return -EPROTO;
36868d5a04a1SMat Martineau 
36878d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
36888d5a04a1SMat Martineau 
36898d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
36908d5a04a1SMat Martineau 
36918d5a04a1SMat Martineau 	return 0;
36928d5a04a1SMat Martineau }
36938d5a04a1SMat Martineau 
3694e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
3695de73115aSClaudio Takahasi 							u16 to_multiplier)
3696de73115aSClaudio Takahasi {
3697de73115aSClaudio Takahasi 	u16 max_latency;
3698de73115aSClaudio Takahasi 
3699de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
3700de73115aSClaudio Takahasi 		return -EINVAL;
3701de73115aSClaudio Takahasi 
3702de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
3703de73115aSClaudio Takahasi 		return -EINVAL;
3704de73115aSClaudio Takahasi 
3705de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
3706de73115aSClaudio Takahasi 		return -EINVAL;
3707de73115aSClaudio Takahasi 
3708de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
3709de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
3710de73115aSClaudio Takahasi 		return -EINVAL;
3711de73115aSClaudio Takahasi 
3712de73115aSClaudio Takahasi 	return 0;
3713de73115aSClaudio Takahasi }
3714de73115aSClaudio Takahasi 
3715de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
3716de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
3717de73115aSClaudio Takahasi {
3718de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
3719de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
3720de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
3721de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
37222ce603ebSClaudio Takahasi 	int err;
3723de73115aSClaudio Takahasi 
3724de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
3725de73115aSClaudio Takahasi 		return -EINVAL;
3726de73115aSClaudio Takahasi 
3727de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
3728de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
3729de73115aSClaudio Takahasi 		return -EPROTO;
3730de73115aSClaudio Takahasi 
3731de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
3732de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
3733de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
3734de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
3735de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
3736de73115aSClaudio Takahasi 
3737de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
3738de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
3739de73115aSClaudio Takahasi 
3740de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
37412ce603ebSClaudio Takahasi 
37422ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
37432ce603ebSClaudio Takahasi 	if (err)
3744de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
3745de73115aSClaudio Takahasi 	else
3746de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
3747de73115aSClaudio Takahasi 
3748de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
3749de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
3750de73115aSClaudio Takahasi 
37512ce603ebSClaudio Takahasi 	if (!err)
37522ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
37532ce603ebSClaudio Takahasi 
3754de73115aSClaudio Takahasi 	return 0;
3755de73115aSClaudio Takahasi }
3756de73115aSClaudio Takahasi 
37573300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
37583300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
37593300d9a9SClaudio Takahasi {
37603300d9a9SClaudio Takahasi 	int err = 0;
37613300d9a9SClaudio Takahasi 
37623300d9a9SClaudio Takahasi 	switch (cmd->code) {
37633300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
37643300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
37653300d9a9SClaudio Takahasi 		break;
37663300d9a9SClaudio Takahasi 
37673300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
37683300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
37693300d9a9SClaudio Takahasi 		break;
37703300d9a9SClaudio Takahasi 
37713300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
37723300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
37733300d9a9SClaudio Takahasi 		break;
37743300d9a9SClaudio Takahasi 
37753300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
37763300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
37773300d9a9SClaudio Takahasi 		break;
37783300d9a9SClaudio Takahasi 
37793300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
37803300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
37813300d9a9SClaudio Takahasi 		break;
37823300d9a9SClaudio Takahasi 
37833300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
37843300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
37853300d9a9SClaudio Takahasi 		break;
37863300d9a9SClaudio Takahasi 
37873300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
37883300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
37893300d9a9SClaudio Takahasi 		break;
37903300d9a9SClaudio Takahasi 
37913300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
37923300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
37933300d9a9SClaudio Takahasi 		break;
37943300d9a9SClaudio Takahasi 
37953300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
37963300d9a9SClaudio Takahasi 		break;
37973300d9a9SClaudio Takahasi 
37983300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
37993300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
38003300d9a9SClaudio Takahasi 		break;
38013300d9a9SClaudio Takahasi 
38023300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
38033300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
38043300d9a9SClaudio Takahasi 		break;
38053300d9a9SClaudio Takahasi 
3806f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
3807f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
3808f94ff6ffSMat Martineau 		break;
3809f94ff6ffSMat Martineau 
3810f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
3811f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
3812f94ff6ffSMat Martineau 		break;
3813f94ff6ffSMat Martineau 
38148d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
38158d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
38168d5a04a1SMat Martineau 		break;
38178d5a04a1SMat Martineau 
38188d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
38198d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
38208d5a04a1SMat Martineau 		break;
38218d5a04a1SMat Martineau 
38228d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
38238d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
38248d5a04a1SMat Martineau 		break;
38258d5a04a1SMat Martineau 
38268d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
38278d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
38288d5a04a1SMat Martineau 		break;
38298d5a04a1SMat Martineau 
38303300d9a9SClaudio Takahasi 	default:
38313300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
38323300d9a9SClaudio Takahasi 		err = -EINVAL;
38333300d9a9SClaudio Takahasi 		break;
38343300d9a9SClaudio Takahasi 	}
38353300d9a9SClaudio Takahasi 
38363300d9a9SClaudio Takahasi 	return err;
38373300d9a9SClaudio Takahasi }
38383300d9a9SClaudio Takahasi 
38393300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
38403300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
38413300d9a9SClaudio Takahasi {
38423300d9a9SClaudio Takahasi 	switch (cmd->code) {
38433300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
38443300d9a9SClaudio Takahasi 		return 0;
38453300d9a9SClaudio Takahasi 
38463300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
3847de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
38483300d9a9SClaudio Takahasi 
38493300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
38503300d9a9SClaudio Takahasi 		return 0;
38513300d9a9SClaudio Takahasi 
38523300d9a9SClaudio Takahasi 	default:
38533300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
38543300d9a9SClaudio Takahasi 		return -EINVAL;
38553300d9a9SClaudio Takahasi 	}
38563300d9a9SClaudio Takahasi }
38573300d9a9SClaudio Takahasi 
38583300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
38593300d9a9SClaudio Takahasi 							struct sk_buff *skb)
38600a708f8fSGustavo F. Padovan {
38610a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
38620a708f8fSGustavo F. Padovan 	int len = skb->len;
38630a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
38643300d9a9SClaudio Takahasi 	int err;
38650a708f8fSGustavo F. Padovan 
38660a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
38670a708f8fSGustavo F. Padovan 
38680a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
38690a708f8fSGustavo F. Padovan 		u16 cmd_len;
38700a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
38710a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
38720a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
38730a708f8fSGustavo F. Padovan 
38740a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
38750a708f8fSGustavo F. Padovan 
38760a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
38770a708f8fSGustavo F. Padovan 
38780a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
38790a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
38800a708f8fSGustavo F. Padovan 			break;
38810a708f8fSGustavo F. Padovan 		}
38820a708f8fSGustavo F. Padovan 
38833300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
38843300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
38853300d9a9SClaudio Takahasi 		else
38863300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
38870a708f8fSGustavo F. Padovan 
38880a708f8fSGustavo F. Padovan 		if (err) {
3889e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
38902c6d1a2eSGustavo F. Padovan 
38912c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
38920a708f8fSGustavo F. Padovan 
38930a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
3894e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
38950a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
38960a708f8fSGustavo F. Padovan 		}
38970a708f8fSGustavo F. Padovan 
38980a708f8fSGustavo F. Padovan 		data += cmd_len;
38990a708f8fSGustavo F. Padovan 		len  -= cmd_len;
39000a708f8fSGustavo F. Padovan 	}
39010a708f8fSGustavo F. Padovan 
39020a708f8fSGustavo F. Padovan 	kfree_skb(skb);
39030a708f8fSGustavo F. Padovan }
39040a708f8fSGustavo F. Padovan 
390547d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
39060a708f8fSGustavo F. Padovan {
39070a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
3908e4ca6d98SAndrei Emeltchenko 	int hdr_size;
3909e4ca6d98SAndrei Emeltchenko 
3910e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3911e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
3912e4ca6d98SAndrei Emeltchenko 	else
3913e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
39140a708f8fSGustavo F. Padovan 
391547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
391603a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
39170a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
39180a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
39190a708f8fSGustavo F. Padovan 
39200a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
39210a708f8fSGustavo F. Padovan 			return -EBADMSG;
39220a708f8fSGustavo F. Padovan 	}
39230a708f8fSGustavo F. Padovan 	return 0;
39240a708f8fSGustavo F. Padovan }
39250a708f8fSGustavo F. Padovan 
3926525cd185SGustavo F. Padovan static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
39270a708f8fSGustavo F. Padovan {
392888843ab0SAndrei Emeltchenko 	u32 control = 0;
39290a708f8fSGustavo F. Padovan 
39306a026610SGustavo F. Padovan 	chan->frames_sent = 0;
39310a708f8fSGustavo F. Padovan 
39320b209faeSAndrei Emeltchenko 	control |= __set_reqseq(chan, chan->buffer_seq);
39330a708f8fSGustavo F. Padovan 
3934e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
3935ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
3936525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
3937e2ab4353SGustavo F. Padovan 		set_bit(CONN_RNR_SENT, &chan->conn_state);
39380a708f8fSGustavo F. Padovan 	}
39390a708f8fSGustavo F. Padovan 
3940e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
3941525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
39420a708f8fSGustavo F. Padovan 
3943525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
39440a708f8fSGustavo F. Padovan 
3945e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
39466a026610SGustavo F. Padovan 			chan->frames_sent == 0) {
3947ab784b73SAndrei Emeltchenko 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
3948525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
39490a708f8fSGustavo F. Padovan 	}
39500a708f8fSGustavo F. Padovan }
39510a708f8fSGustavo F. Padovan 
3952fb45de7dSAndrei Emeltchenko static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
39530a708f8fSGustavo F. Padovan {
39540a708f8fSGustavo F. Padovan 	struct sk_buff *next_skb;
39550a708f8fSGustavo F. Padovan 	int tx_seq_offset, next_tx_seq_offset;
39560a708f8fSGustavo F. Padovan 
39573ce3514fSMat Martineau 	bt_cb(skb)->control.txseq = tx_seq;
39583ce3514fSMat Martineau 	bt_cb(skb)->control.sar = sar;
39590a708f8fSGustavo F. Padovan 
3960f1c6775bSGustavo F. Padovan 	next_skb = skb_peek(&chan->srej_q);
39610a708f8fSGustavo F. Padovan 
3962836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
39630a708f8fSGustavo F. Padovan 
3964039d9572SSzymon Janc 	while (next_skb) {
39653ce3514fSMat Martineau 		if (bt_cb(next_skb)->control.txseq == tx_seq)
39660a708f8fSGustavo F. Padovan 			return -EINVAL;
39670a708f8fSGustavo F. Padovan 
3968836be934SAndrei Emeltchenko 		next_tx_seq_offset = __seq_offset(chan,
39693ce3514fSMat Martineau 			bt_cb(next_skb)->control.txseq, chan->buffer_seq);
39700a708f8fSGustavo F. Padovan 
39710a708f8fSGustavo F. Padovan 		if (next_tx_seq_offset > tx_seq_offset) {
3972f1c6775bSGustavo F. Padovan 			__skb_queue_before(&chan->srej_q, next_skb, skb);
39730a708f8fSGustavo F. Padovan 			return 0;
39740a708f8fSGustavo F. Padovan 		}
39750a708f8fSGustavo F. Padovan 
3976f1c6775bSGustavo F. Padovan 		if (skb_queue_is_last(&chan->srej_q, next_skb))
3977039d9572SSzymon Janc 			next_skb = NULL;
3978039d9572SSzymon Janc 		else
3979039d9572SSzymon Janc 			next_skb = skb_queue_next(&chan->srej_q, next_skb);
3980039d9572SSzymon Janc 	}
39810a708f8fSGustavo F. Padovan 
3982f1c6775bSGustavo F. Padovan 	__skb_queue_tail(&chan->srej_q, skb);
39830a708f8fSGustavo F. Padovan 
39840a708f8fSGustavo F. Padovan 	return 0;
39850a708f8fSGustavo F. Padovan }
39860a708f8fSGustavo F. Padovan 
398784084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
398884084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
39890a708f8fSGustavo F. Padovan {
399084084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
399184084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
399284084a31SMat Martineau 	 */
399384084a31SMat Martineau 	if (!skb_has_frag_list(skb))
399484084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
399584084a31SMat Martineau 
399684084a31SMat Martineau 	new_frag->next = NULL;
399784084a31SMat Martineau 
399884084a31SMat Martineau 	(*last_frag)->next = new_frag;
399984084a31SMat Martineau 	*last_frag = new_frag;
400084084a31SMat Martineau 
400184084a31SMat Martineau 	skb->len += new_frag->len;
400284084a31SMat Martineau 	skb->data_len += new_frag->len;
400384084a31SMat Martineau 	skb->truesize += new_frag->truesize;
400484084a31SMat Martineau }
400584084a31SMat Martineau 
400688843ab0SAndrei Emeltchenko static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
400784084a31SMat Martineau {
400884084a31SMat Martineau 	int err = -EINVAL;
40090a708f8fSGustavo F. Padovan 
40107e0ef6eeSAndrei Emeltchenko 	switch (__get_ctrl_sar(chan, control)) {
40117e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
401284084a31SMat Martineau 		if (chan->sdu)
401384084a31SMat Martineau 			break;
40140a708f8fSGustavo F. Padovan 
401584084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
401684084a31SMat Martineau 		break;
40170a708f8fSGustavo F. Padovan 
40187e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
401984084a31SMat Martineau 		if (chan->sdu)
402084084a31SMat Martineau 			break;
40210a708f8fSGustavo F. Padovan 
40226f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
402303a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
40240a708f8fSGustavo F. Padovan 
402584084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
402684084a31SMat Martineau 			err = -EMSGSIZE;
402784084a31SMat Martineau 			break;
402884084a31SMat Martineau 		}
40290a708f8fSGustavo F. Padovan 
403084084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
403184084a31SMat Martineau 			break;
403284084a31SMat Martineau 
403384084a31SMat Martineau 		chan->sdu = skb;
403484084a31SMat Martineau 		chan->sdu_last_frag = skb;
403584084a31SMat Martineau 
403684084a31SMat Martineau 		skb = NULL;
403784084a31SMat Martineau 		err = 0;
40380a708f8fSGustavo F. Padovan 		break;
40390a708f8fSGustavo F. Padovan 
40407e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
40416f61fd47SGustavo F. Padovan 		if (!chan->sdu)
404284084a31SMat Martineau 			break;
40430a708f8fSGustavo F. Padovan 
404484084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
404584084a31SMat Martineau 				&chan->sdu_last_frag);
404684084a31SMat Martineau 		skb = NULL;
40470a708f8fSGustavo F. Padovan 
404884084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
404984084a31SMat Martineau 			break;
40500a708f8fSGustavo F. Padovan 
405184084a31SMat Martineau 		err = 0;
40520a708f8fSGustavo F. Padovan 		break;
40530a708f8fSGustavo F. Padovan 
40547e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
40556f61fd47SGustavo F. Padovan 		if (!chan->sdu)
405684084a31SMat Martineau 			break;
40570a708f8fSGustavo F. Padovan 
405884084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
405984084a31SMat Martineau 				&chan->sdu_last_frag);
406084084a31SMat Martineau 		skb = NULL;
40610a708f8fSGustavo F. Padovan 
406284084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
406384084a31SMat Martineau 			break;
40640a708f8fSGustavo F. Padovan 
406584084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
40660a708f8fSGustavo F. Padovan 
406784084a31SMat Martineau 		if (!err) {
406884084a31SMat Martineau 			/* Reassembly complete */
406984084a31SMat Martineau 			chan->sdu = NULL;
407084084a31SMat Martineau 			chan->sdu_last_frag = NULL;
407184084a31SMat Martineau 			chan->sdu_len = 0;
40720a708f8fSGustavo F. Padovan 		}
40730a708f8fSGustavo F. Padovan 		break;
40740a708f8fSGustavo F. Padovan 	}
40750a708f8fSGustavo F. Padovan 
407684084a31SMat Martineau 	if (err) {
40770a708f8fSGustavo F. Padovan 		kfree_skb(skb);
40786f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
40796f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
408084084a31SMat Martineau 		chan->sdu_last_frag = NULL;
408184084a31SMat Martineau 		chan->sdu_len = 0;
408284084a31SMat Martineau 	}
40830a708f8fSGustavo F. Padovan 
408484084a31SMat Martineau 	return err;
40850a708f8fSGustavo F. Padovan }
40860a708f8fSGustavo F. Padovan 
408726f880d2SMat Martineau static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
40880a708f8fSGustavo F. Padovan {
408926f880d2SMat Martineau 	BT_DBG("chan %p, Enter local busy", chan);
409026f880d2SMat Martineau 
409126f880d2SMat Martineau 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
40923c588192SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
409326f880d2SMat Martineau 
409477f918bcSSzymon Janc 	__set_ack_timer(chan);
40950a708f8fSGustavo F. Padovan }
40960a708f8fSGustavo F. Padovan 
409726f880d2SMat Martineau static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
409826f880d2SMat Martineau {
409988843ab0SAndrei Emeltchenko 	u32 control;
41000a708f8fSGustavo F. Padovan 
4101e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
41020a708f8fSGustavo F. Padovan 		goto done;
41030a708f8fSGustavo F. Padovan 
41040b209faeSAndrei Emeltchenko 	control = __set_reqseq(chan, chan->buffer_seq);
4105e3781735SAndrei Emeltchenko 	control |= __set_ctrl_poll(chan);
4106ab784b73SAndrei Emeltchenko 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
4107525cd185SGustavo F. Padovan 	l2cap_send_sframe(chan, control);
41086a026610SGustavo F. Padovan 	chan->retry_count = 1;
41090a708f8fSGustavo F. Padovan 
41101a09bcb9SGustavo F. Padovan 	__clear_retrans_timer(chan);
41111a09bcb9SGustavo F. Padovan 	__set_monitor_timer(chan);
41120a708f8fSGustavo F. Padovan 
4113e2ab4353SGustavo F. Padovan 	set_bit(CONN_WAIT_F, &chan->conn_state);
41140a708f8fSGustavo F. Padovan 
41150a708f8fSGustavo F. Padovan done:
4116e2ab4353SGustavo F. Padovan 	clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
4117e2ab4353SGustavo F. Padovan 	clear_bit(CONN_RNR_SENT, &chan->conn_state);
41180a708f8fSGustavo F. Padovan 
411949208c9cSGustavo F. Padovan 	BT_DBG("chan %p, Exit local busy", chan);
41200a708f8fSGustavo F. Padovan }
41210a708f8fSGustavo F. Padovan 
4122e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
41230a708f8fSGustavo F. Padovan {
4124e328140fSMat Martineau 	if (chan->mode == L2CAP_MODE_ERTM) {
4125e328140fSMat Martineau 		if (busy)
412626f880d2SMat Martineau 			l2cap_ertm_enter_local_busy(chan);
4127e328140fSMat Martineau 		else
4128e328140fSMat Martineau 			l2cap_ertm_exit_local_busy(chan);
41290a708f8fSGustavo F. Padovan 	}
41300a708f8fSGustavo F. Padovan }
41310a708f8fSGustavo F. Padovan 
4132fb45de7dSAndrei Emeltchenko static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
41330a708f8fSGustavo F. Padovan {
41340a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
413588843ab0SAndrei Emeltchenko 	u32 control;
41360a708f8fSGustavo F. Padovan 
4137e328140fSMat Martineau 	while ((skb = skb_peek(&chan->srej_q)) &&
4138e328140fSMat Martineau 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4139e328140fSMat Martineau 		int err;
4140e328140fSMat Martineau 
41413ce3514fSMat Martineau 		if (bt_cb(skb)->control.txseq != tx_seq)
41420a708f8fSGustavo F. Padovan 			break;
41430a708f8fSGustavo F. Padovan 
4144f1c6775bSGustavo F. Padovan 		skb = skb_dequeue(&chan->srej_q);
41453ce3514fSMat Martineau 		control = __set_ctrl_sar(chan, bt_cb(skb)->control.sar);
414684084a31SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, control);
4147e328140fSMat Martineau 
4148e328140fSMat Martineau 		if (err < 0) {
4149e328140fSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4150e328140fSMat Martineau 			break;
4151e328140fSMat Martineau 		}
4152e328140fSMat Martineau 
4153836be934SAndrei Emeltchenko 		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
4154836be934SAndrei Emeltchenko 		tx_seq = __next_seq(chan, tx_seq);
41550a708f8fSGustavo F. Padovan 	}
41560a708f8fSGustavo F. Padovan }
41570a708f8fSGustavo F. Padovan 
4158fb45de7dSAndrei Emeltchenko static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
41590a708f8fSGustavo F. Padovan {
41600a708f8fSGustavo F. Padovan 	struct srej_list *l, *tmp;
416188843ab0SAndrei Emeltchenko 	u32 control;
41620a708f8fSGustavo F. Padovan 
416339d5a3eeSGustavo F. Padovan 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
41640a708f8fSGustavo F. Padovan 		if (l->tx_seq == tx_seq) {
41650a708f8fSGustavo F. Padovan 			list_del(&l->list);
41660a708f8fSGustavo F. Padovan 			kfree(l);
41670a708f8fSGustavo F. Padovan 			return;
41680a708f8fSGustavo F. Padovan 		}
4169ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
41700b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, l->tx_seq);
4171525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
41720a708f8fSGustavo F. Padovan 		list_del(&l->list);
417339d5a3eeSGustavo F. Padovan 		list_add_tail(&l->list, &chan->srej_l);
41740a708f8fSGustavo F. Padovan 	}
41750a708f8fSGustavo F. Padovan }
41760a708f8fSGustavo F. Padovan 
4177aef89f21SSzymon Janc static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
41780a708f8fSGustavo F. Padovan {
41790a708f8fSGustavo F. Padovan 	struct srej_list *new;
418088843ab0SAndrei Emeltchenko 	u32 control;
41810a708f8fSGustavo F. Padovan 
418242e5c802SGustavo F. Padovan 	while (tx_seq != chan->expected_tx_seq) {
4183ab784b73SAndrei Emeltchenko 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
41840b209faeSAndrei Emeltchenko 		control |= __set_reqseq(chan, chan->expected_tx_seq);
41853c588192SMat Martineau 		l2cap_seq_list_append(&chan->srej_list, chan->expected_tx_seq);
4186525cd185SGustavo F. Padovan 		l2cap_send_sframe(chan, control);
41870a708f8fSGustavo F. Padovan 
41880a708f8fSGustavo F. Padovan 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
4189aef89f21SSzymon Janc 		if (!new)
4190aef89f21SSzymon Janc 			return -ENOMEM;
4191aef89f21SSzymon Janc 
419242e5c802SGustavo F. Padovan 		new->tx_seq = chan->expected_tx_seq;
4193836be934SAndrei Emeltchenko 
4194836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4195836be934SAndrei Emeltchenko 
419639d5a3eeSGustavo F. Padovan 		list_add_tail(&new->list, &chan->srej_l);
41970a708f8fSGustavo F. Padovan 	}
4198836be934SAndrei Emeltchenko 
4199836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
4200aef89f21SSzymon Janc 
4201aef89f21SSzymon Janc 	return 0;
42020a708f8fSGustavo F. Padovan }
42030a708f8fSGustavo F. Padovan 
420488843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
42050a708f8fSGustavo F. Padovan {
4206fb45de7dSAndrei Emeltchenko 	u16 tx_seq = __get_txseq(chan, rx_control);
42070b209faeSAndrei Emeltchenko 	u16 req_seq = __get_reqseq(chan, rx_control);
42087e0ef6eeSAndrei Emeltchenko 	u8 sar = __get_ctrl_sar(chan, rx_control);
42090a708f8fSGustavo F. Padovan 	int tx_seq_offset, expected_tx_seq_offset;
421047d1ec61SGustavo F. Padovan 	int num_to_ack = (chan->tx_win/6) + 1;
42110a708f8fSGustavo F. Padovan 	int err = 0;
42120a708f8fSGustavo F. Padovan 
421388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
4214525cd185SGustavo F. Padovan 							tx_seq, rx_control);
42150a708f8fSGustavo F. Padovan 
421603f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4217e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
42181a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
42196a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
42201a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4221e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
42220a708f8fSGustavo F. Padovan 	}
42230a708f8fSGustavo F. Padovan 
422442e5c802SGustavo F. Padovan 	chan->expected_ack_seq = req_seq;
422542e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
42260a708f8fSGustavo F. Padovan 
4227836be934SAndrei Emeltchenko 	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
42280a708f8fSGustavo F. Padovan 
42290a708f8fSGustavo F. Padovan 	/* invalid tx_seq */
423047d1ec61SGustavo F. Padovan 	if (tx_seq_offset >= chan->tx_win) {
42318c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
42320a708f8fSGustavo F. Padovan 		goto drop;
42330a708f8fSGustavo F. Padovan 	}
42340a708f8fSGustavo F. Padovan 
423577f918bcSSzymon Janc 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
423677f918bcSSzymon Janc 		if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
423777f918bcSSzymon Janc 			l2cap_send_ack(chan);
42380a708f8fSGustavo F. Padovan 		goto drop;
423977f918bcSSzymon Janc 	}
42400a708f8fSGustavo F. Padovan 
424102f1b641SMat Martineau 	if (tx_seq == chan->expected_tx_seq)
424202f1b641SMat Martineau 		goto expected;
424302f1b641SMat Martineau 
4244e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
42450a708f8fSGustavo F. Padovan 		struct srej_list *first;
42460a708f8fSGustavo F. Padovan 
424739d5a3eeSGustavo F. Padovan 		first = list_first_entry(&chan->srej_l,
42480a708f8fSGustavo F. Padovan 				struct srej_list, list);
42490a708f8fSGustavo F. Padovan 		if (tx_seq == first->tx_seq) {
425042e5c802SGustavo F. Padovan 			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
4251525cd185SGustavo F. Padovan 			l2cap_check_srej_gap(chan, tx_seq);
42520a708f8fSGustavo F. Padovan 
42530a708f8fSGustavo F. Padovan 			list_del(&first->list);
42540a708f8fSGustavo F. Padovan 			kfree(first);
42550a708f8fSGustavo F. Padovan 
425639d5a3eeSGustavo F. Padovan 			if (list_empty(&chan->srej_l)) {
425742e5c802SGustavo F. Padovan 				chan->buffer_seq = chan->buffer_seq_srej;
4258e2ab4353SGustavo F. Padovan 				clear_bit(CONN_SREJ_SENT, &chan->conn_state);
4259525cd185SGustavo F. Padovan 				l2cap_send_ack(chan);
426049208c9cSGustavo F. Padovan 				BT_DBG("chan %p, Exit SREJ_SENT", chan);
42610a708f8fSGustavo F. Padovan 			}
42620a708f8fSGustavo F. Padovan 		} else {
42630a708f8fSGustavo F. Padovan 			struct srej_list *l;
42640a708f8fSGustavo F. Padovan 
42650a708f8fSGustavo F. Padovan 			/* duplicated tx_seq */
426642e5c802SGustavo F. Padovan 			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)
42670a708f8fSGustavo F. Padovan 				goto drop;
42680a708f8fSGustavo F. Padovan 
426939d5a3eeSGustavo F. Padovan 			list_for_each_entry(l, &chan->srej_l, list) {
42700a708f8fSGustavo F. Padovan 				if (l->tx_seq == tx_seq) {
4271525cd185SGustavo F. Padovan 					l2cap_resend_srejframe(chan, tx_seq);
42720a708f8fSGustavo F. Padovan 					return 0;
42730a708f8fSGustavo F. Padovan 				}
42740a708f8fSGustavo F. Padovan 			}
4275aef89f21SSzymon Janc 
4276aef89f21SSzymon Janc 			err = l2cap_send_srejframe(chan, tx_seq);
4277aef89f21SSzymon Janc 			if (err < 0) {
4278aef89f21SSzymon Janc 				l2cap_send_disconn_req(chan->conn, chan, -err);
4279aef89f21SSzymon Janc 				return err;
4280aef89f21SSzymon Janc 			}
42810a708f8fSGustavo F. Padovan 		}
42820a708f8fSGustavo F. Padovan 	} else {
4283836be934SAndrei Emeltchenko 		expected_tx_seq_offset = __seq_offset(chan,
4284836be934SAndrei Emeltchenko 				chan->expected_tx_seq, chan->buffer_seq);
42850a708f8fSGustavo F. Padovan 
42860a708f8fSGustavo F. Padovan 		/* duplicated tx_seq */
42870a708f8fSGustavo F. Padovan 		if (tx_seq_offset < expected_tx_seq_offset)
42880a708f8fSGustavo F. Padovan 			goto drop;
42890a708f8fSGustavo F. Padovan 
4290e2ab4353SGustavo F. Padovan 		set_bit(CONN_SREJ_SENT, &chan->conn_state);
42910a708f8fSGustavo F. Padovan 
429249208c9cSGustavo F. Padovan 		BT_DBG("chan %p, Enter SREJ", chan);
42930a708f8fSGustavo F. Padovan 
429439d5a3eeSGustavo F. Padovan 		INIT_LIST_HEAD(&chan->srej_l);
429542e5c802SGustavo F. Padovan 		chan->buffer_seq_srej = chan->buffer_seq;
42960a708f8fSGustavo F. Padovan 
4297f1c6775bSGustavo F. Padovan 		__skb_queue_head_init(&chan->srej_q);
429842e5c802SGustavo F. Padovan 		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
42990a708f8fSGustavo F. Padovan 
43000ef3ef0fSSzymon Janc 		/* Set P-bit only if there are some I-frames to ack. */
43010ef3ef0fSSzymon Janc 		if (__clear_ack_timer(chan))
4302e2ab4353SGustavo F. Padovan 			set_bit(CONN_SEND_PBIT, &chan->conn_state);
43030a708f8fSGustavo F. Padovan 
4304aef89f21SSzymon Janc 		err = l2cap_send_srejframe(chan, tx_seq);
4305aef89f21SSzymon Janc 		if (err < 0) {
4306aef89f21SSzymon Janc 			l2cap_send_disconn_req(chan->conn, chan, -err);
4307aef89f21SSzymon Janc 			return err;
4308aef89f21SSzymon Janc 		}
43090a708f8fSGustavo F. Padovan 	}
43100a708f8fSGustavo F. Padovan 	return 0;
43110a708f8fSGustavo F. Padovan 
43120a708f8fSGustavo F. Padovan expected:
4313836be934SAndrei Emeltchenko 	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
43140a708f8fSGustavo F. Padovan 
4315e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
43163ce3514fSMat Martineau 		bt_cb(skb)->control.txseq = tx_seq;
43173ce3514fSMat Martineau 		bt_cb(skb)->control.sar = sar;
4318f1c6775bSGustavo F. Padovan 		__skb_queue_tail(&chan->srej_q, skb);
43190a708f8fSGustavo F. Padovan 		return 0;
43200a708f8fSGustavo F. Padovan 	}
43210a708f8fSGustavo F. Padovan 
432284084a31SMat Martineau 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
4323836be934SAndrei Emeltchenko 	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
4324836be934SAndrei Emeltchenko 
4325e328140fSMat Martineau 	if (err < 0) {
4326e328140fSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4327e328140fSMat Martineau 		return err;
4328e328140fSMat Martineau 	}
43290a708f8fSGustavo F. Padovan 
433003f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4331e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4332525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43330a708f8fSGustavo F. Padovan 	}
43340a708f8fSGustavo F. Padovan 
43350a708f8fSGustavo F. Padovan 
43366a026610SGustavo F. Padovan 	chan->num_acked = (chan->num_acked + 1) % num_to_ack;
43376a026610SGustavo F. Padovan 	if (chan->num_acked == num_to_ack - 1)
4338525cd185SGustavo F. Padovan 		l2cap_send_ack(chan);
43394d611e4dSGustavo F. Padovan 	else
43404d611e4dSGustavo F. Padovan 		__set_ack_timer(chan);
43410a708f8fSGustavo F. Padovan 
43420a708f8fSGustavo F. Padovan 	return 0;
43430a708f8fSGustavo F. Padovan 
43440a708f8fSGustavo F. Padovan drop:
43450a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43460a708f8fSGustavo F. Padovan 	return 0;
43470a708f8fSGustavo F. Padovan }
43480a708f8fSGustavo F. Padovan 
434988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
43500a708f8fSGustavo F. Padovan {
435188843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
43520b209faeSAndrei Emeltchenko 				__get_reqseq(chan, rx_control), rx_control);
43530a708f8fSGustavo F. Padovan 
43540b209faeSAndrei Emeltchenko 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
435542e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
43560a708f8fSGustavo F. Padovan 
4357e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4358e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4359e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
4360e2ab4353SGustavo F. Padovan 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
43616a026610SGustavo F. Padovan 					(chan->unacked_frames > 0))
43621a09bcb9SGustavo F. Padovan 				__set_retrans_timer(chan);
43630a708f8fSGustavo F. Padovan 
4364e2ab4353SGustavo F. Padovan 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4365525cd185SGustavo F. Padovan 			l2cap_send_srejtail(chan);
43660a708f8fSGustavo F. Padovan 		} else {
4367525cd185SGustavo F. Padovan 			l2cap_send_i_or_rr_or_rnr(chan);
43680a708f8fSGustavo F. Padovan 		}
43690a708f8fSGustavo F. Padovan 
437003f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4371e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
43720a708f8fSGustavo F. Padovan 
4373e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4374525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
43750a708f8fSGustavo F. Padovan 
43760a708f8fSGustavo F. Padovan 	} else {
4377e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
43786a026610SGustavo F. Padovan 				(chan->unacked_frames > 0))
43791a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
43800a708f8fSGustavo F. Padovan 
4381e2ab4353SGustavo F. Padovan 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4382e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
4383525cd185SGustavo F. Padovan 			l2cap_send_ack(chan);
43840a708f8fSGustavo F. Padovan 		else
4385525cd185SGustavo F. Padovan 			l2cap_ertm_send(chan);
43860a708f8fSGustavo F. Padovan 	}
43870a708f8fSGustavo F. Padovan }
43880a708f8fSGustavo F. Padovan 
438988843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
43900a708f8fSGustavo F. Padovan {
43910b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
43920a708f8fSGustavo F. Padovan 
439388843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
43940a708f8fSGustavo F. Padovan 
4395e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
43960a708f8fSGustavo F. Padovan 
439742e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
439842e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
43990a708f8fSGustavo F. Padovan 
440003f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control)) {
4401e2ab4353SGustavo F. Padovan 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4402525cd185SGustavo F. Padovan 			l2cap_retransmit_frames(chan);
44030a708f8fSGustavo F. Padovan 	} else {
4404525cd185SGustavo F. Padovan 		l2cap_retransmit_frames(chan);
44050a708f8fSGustavo F. Padovan 
4406e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state))
4407e2ab4353SGustavo F. Padovan 			set_bit(CONN_REJ_ACT, &chan->conn_state);
44080a708f8fSGustavo F. Padovan 	}
44090a708f8fSGustavo F. Padovan }
441088843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
44110a708f8fSGustavo F. Padovan {
44120b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44130a708f8fSGustavo F. Padovan 
441488843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44150a708f8fSGustavo F. Padovan 
4416e2ab4353SGustavo F. Padovan 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
44170a708f8fSGustavo F. Padovan 
4418e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
441942e5c802SGustavo F. Padovan 		chan->expected_ack_seq = tx_seq;
442042e5c802SGustavo F. Padovan 		l2cap_drop_acked_frames(chan);
44210a708f8fSGustavo F. Padovan 
4422e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4423525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
44240a708f8fSGustavo F. Padovan 
4425525cd185SGustavo F. Padovan 		l2cap_ertm_send(chan);
44260a708f8fSGustavo F. Padovan 
4427e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44286a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4429e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44300a708f8fSGustavo F. Padovan 		}
443103f6715dSAndrei Emeltchenko 	} else if (__is_ctrl_final(chan, rx_control)) {
4432e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
44336a026610SGustavo F. Padovan 				chan->srej_save_reqseq == tx_seq)
4434e2ab4353SGustavo F. Padovan 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
44350a708f8fSGustavo F. Padovan 		else
4436525cd185SGustavo F. Padovan 			l2cap_retransmit_one_frame(chan, tx_seq);
44370a708f8fSGustavo F. Padovan 	} else {
4438525cd185SGustavo F. Padovan 		l2cap_retransmit_one_frame(chan, tx_seq);
4439e2ab4353SGustavo F. Padovan 		if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
44406a026610SGustavo F. Padovan 			chan->srej_save_reqseq = tx_seq;
4441e2ab4353SGustavo F. Padovan 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
44420a708f8fSGustavo F. Padovan 		}
44430a708f8fSGustavo F. Padovan 	}
44440a708f8fSGustavo F. Padovan }
44450a708f8fSGustavo F. Padovan 
444688843ab0SAndrei Emeltchenko static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
44470a708f8fSGustavo F. Padovan {
44480b209faeSAndrei Emeltchenko 	u16 tx_seq = __get_reqseq(chan, rx_control);
44490a708f8fSGustavo F. Padovan 
445088843ab0SAndrei Emeltchenko 	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
44510a708f8fSGustavo F. Padovan 
4452e2ab4353SGustavo F. Padovan 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
445342e5c802SGustavo F. Padovan 	chan->expected_ack_seq = tx_seq;
445442e5c802SGustavo F. Padovan 	l2cap_drop_acked_frames(chan);
44550a708f8fSGustavo F. Padovan 
4456e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control))
4457e2ab4353SGustavo F. Padovan 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
44580a708f8fSGustavo F. Padovan 
4459e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
44601a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
4461e3781735SAndrei Emeltchenko 		if (__is_ctrl_poll(chan, rx_control))
4462525cd185SGustavo F. Padovan 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
44630a708f8fSGustavo F. Padovan 		return;
44640a708f8fSGustavo F. Padovan 	}
44650a708f8fSGustavo F. Padovan 
4466e3781735SAndrei Emeltchenko 	if (__is_ctrl_poll(chan, rx_control)) {
4467525cd185SGustavo F. Padovan 		l2cap_send_srejtail(chan);
4468ab784b73SAndrei Emeltchenko 	} else {
4469ab784b73SAndrei Emeltchenko 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
4470ab784b73SAndrei Emeltchenko 		l2cap_send_sframe(chan, rx_control);
4471ab784b73SAndrei Emeltchenko 	}
44720a708f8fSGustavo F. Padovan }
44730a708f8fSGustavo F. Padovan 
447488843ab0SAndrei Emeltchenko static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
44750a708f8fSGustavo F. Padovan {
447688843ab0SAndrei Emeltchenko 	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
44770a708f8fSGustavo F. Padovan 
447803f6715dSAndrei Emeltchenko 	if (__is_ctrl_final(chan, rx_control) &&
4479e2ab4353SGustavo F. Padovan 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
44801a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
44816a026610SGustavo F. Padovan 		if (chan->unacked_frames > 0)
44821a09bcb9SGustavo F. Padovan 			__set_retrans_timer(chan);
4483e2ab4353SGustavo F. Padovan 		clear_bit(CONN_WAIT_F, &chan->conn_state);
44840a708f8fSGustavo F. Padovan 	}
44850a708f8fSGustavo F. Padovan 
4486ab784b73SAndrei Emeltchenko 	switch (__get_ctrl_super(chan, rx_control)) {
4487ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RR:
4488525cd185SGustavo F. Padovan 		l2cap_data_channel_rrframe(chan, rx_control);
44890a708f8fSGustavo F. Padovan 		break;
44900a708f8fSGustavo F. Padovan 
4491ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_REJ:
4492525cd185SGustavo F. Padovan 		l2cap_data_channel_rejframe(chan, rx_control);
44930a708f8fSGustavo F. Padovan 		break;
44940a708f8fSGustavo F. Padovan 
4495ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_SREJ:
4496525cd185SGustavo F. Padovan 		l2cap_data_channel_srejframe(chan, rx_control);
44970a708f8fSGustavo F. Padovan 		break;
44980a708f8fSGustavo F. Padovan 
4499ab784b73SAndrei Emeltchenko 	case L2CAP_SUPER_RNR:
4500525cd185SGustavo F. Padovan 		l2cap_data_channel_rnrframe(chan, rx_control);
45010a708f8fSGustavo F. Padovan 		break;
45020a708f8fSGustavo F. Padovan 	}
45030a708f8fSGustavo F. Padovan 
45040a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45050a708f8fSGustavo F. Padovan 	return 0;
45060a708f8fSGustavo F. Padovan }
45070a708f8fSGustavo F. Padovan 
4508cad8f1d0SSzymon Janc static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
45090a708f8fSGustavo F. Padovan {
451088843ab0SAndrei Emeltchenko 	u32 control;
45110b209faeSAndrei Emeltchenko 	u16 req_seq;
45120a708f8fSGustavo F. Padovan 	int len, next_tx_seq_offset, req_seq_offset;
45130a708f8fSGustavo F. Padovan 
4514b76bbd66SMat Martineau 	__unpack_control(chan, skb);
4515b76bbd66SMat Martineau 
451688843ab0SAndrei Emeltchenko 	control = __get_control(chan, skb->data);
451788843ab0SAndrei Emeltchenko 	skb_pull(skb, __ctrl_size(chan));
45180a708f8fSGustavo F. Padovan 	len = skb->len;
45190a708f8fSGustavo F. Padovan 
45200a708f8fSGustavo F. Padovan 	/*
45210a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
45220a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
45230a708f8fSGustavo F. Padovan 	 * procedures and ask retransmission.
45240a708f8fSGustavo F. Padovan 	 */
452547d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
45260a708f8fSGustavo F. Padovan 		goto drop;
45270a708f8fSGustavo F. Padovan 
4528793c2f1cSAndrei Emeltchenko 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
452903a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
45300a708f8fSGustavo F. Padovan 
453147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
453203a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
45330a708f8fSGustavo F. Padovan 
453447d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
45358c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45360a708f8fSGustavo F. Padovan 		goto drop;
45370a708f8fSGustavo F. Padovan 	}
45380a708f8fSGustavo F. Padovan 
45390b209faeSAndrei Emeltchenko 	req_seq = __get_reqseq(chan, control);
45400a708f8fSGustavo F. Padovan 
4541836be934SAndrei Emeltchenko 	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
4542836be934SAndrei Emeltchenko 
4543836be934SAndrei Emeltchenko 	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
4544836be934SAndrei Emeltchenko 						chan->expected_ack_seq);
45450a708f8fSGustavo F. Padovan 
45460a708f8fSGustavo F. Padovan 	/* check for invalid req-seq */
45470a708f8fSGustavo F. Padovan 	if (req_seq_offset > next_tx_seq_offset) {
45488c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45490a708f8fSGustavo F. Padovan 		goto drop;
45500a708f8fSGustavo F. Padovan 	}
45510a708f8fSGustavo F. Padovan 
4552793c2f1cSAndrei Emeltchenko 	if (!__is_sframe(chan, control)) {
45530a708f8fSGustavo F. Padovan 		if (len < 0) {
45548c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45550a708f8fSGustavo F. Padovan 			goto drop;
45560a708f8fSGustavo F. Padovan 		}
45570a708f8fSGustavo F. Padovan 
4558525cd185SGustavo F. Padovan 		l2cap_data_channel_iframe(chan, control, skb);
45590a708f8fSGustavo F. Padovan 	} else {
45600a708f8fSGustavo F. Padovan 		if (len != 0) {
45610a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
45628c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
45630a708f8fSGustavo F. Padovan 			goto drop;
45640a708f8fSGustavo F. Padovan 		}
45650a708f8fSGustavo F. Padovan 
4566525cd185SGustavo F. Padovan 		l2cap_data_channel_sframe(chan, control, skb);
45670a708f8fSGustavo F. Padovan 	}
45680a708f8fSGustavo F. Padovan 
45690a708f8fSGustavo F. Padovan 	return 0;
45700a708f8fSGustavo F. Padovan 
45710a708f8fSGustavo F. Padovan drop:
45720a708f8fSGustavo F. Padovan 	kfree_skb(skb);
45730a708f8fSGustavo F. Padovan 	return 0;
45740a708f8fSGustavo F. Padovan }
45750a708f8fSGustavo F. Padovan 
45760a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
45770a708f8fSGustavo F. Padovan {
457848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
457988843ab0SAndrei Emeltchenko 	u32 control;
4580fb45de7dSAndrei Emeltchenko 	u16 tx_seq;
45810a708f8fSGustavo F. Padovan 	int len;
45820a708f8fSGustavo F. Padovan 
4583baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
458448454079SGustavo F. Padovan 	if (!chan) {
45850a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
45866be36555SAndrei Emeltchenko 		/* Drop packet and return */
45873379013bSDan Carpenter 		kfree_skb(skb);
45886be36555SAndrei Emeltchenko 		return 0;
45890a708f8fSGustavo F. Padovan 	}
45900a708f8fSGustavo F. Padovan 
45916be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
45920a708f8fSGustavo F. Padovan 
459349208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
45940a708f8fSGustavo F. Padovan 
459589bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
45960a708f8fSGustavo F. Padovan 		goto drop;
45970a708f8fSGustavo F. Padovan 
45980c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
45990a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
46000a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
46010a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
46020a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
46030a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
46040a708f8fSGustavo F. Padovan 
46050c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
46060a708f8fSGustavo F. Padovan 			goto drop;
46070a708f8fSGustavo F. Padovan 
460823070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
46090a708f8fSGustavo F. Padovan 			goto done;
46100a708f8fSGustavo F. Padovan 		break;
46110a708f8fSGustavo F. Padovan 
46120a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
46135ef8cb9eSAndrei Emeltchenko 		l2cap_ertm_data_rcv(chan, skb);
46140a708f8fSGustavo F. Padovan 
46150a708f8fSGustavo F. Padovan 		goto done;
46160a708f8fSGustavo F. Padovan 
46170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
461888843ab0SAndrei Emeltchenko 		control = __get_control(chan, skb->data);
461988843ab0SAndrei Emeltchenko 		skb_pull(skb, __ctrl_size(chan));
46200a708f8fSGustavo F. Padovan 		len = skb->len;
46210a708f8fSGustavo F. Padovan 
462247d1ec61SGustavo F. Padovan 		if (l2cap_check_fcs(chan, skb))
46230a708f8fSGustavo F. Padovan 			goto drop;
46240a708f8fSGustavo F. Padovan 
46257e0ef6eeSAndrei Emeltchenko 		if (__is_sar_start(chan, control))
462603a51213SAndrei Emeltchenko 			len -= L2CAP_SDULEN_SIZE;
46270a708f8fSGustavo F. Padovan 
462847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16)
462903a51213SAndrei Emeltchenko 			len -= L2CAP_FCS_SIZE;
46300a708f8fSGustavo F. Padovan 
4631793c2f1cSAndrei Emeltchenko 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
46320a708f8fSGustavo F. Padovan 			goto drop;
46330a708f8fSGustavo F. Padovan 
4634fb45de7dSAndrei Emeltchenko 		tx_seq = __get_txseq(chan, control);
46350a708f8fSGustavo F. Padovan 
463684084a31SMat Martineau 		if (chan->expected_tx_seq != tx_seq) {
463784084a31SMat Martineau 			/* Frame(s) missing - must discard partial SDU */
463884084a31SMat Martineau 			kfree_skb(chan->sdu);
463984084a31SMat Martineau 			chan->sdu = NULL;
464084084a31SMat Martineau 			chan->sdu_last_frag = NULL;
464184084a31SMat Martineau 			chan->sdu_len = 0;
464284084a31SMat Martineau 
464384084a31SMat Martineau 			/* TODO: Notify userland of missing data */
464484084a31SMat Martineau 		}
464584084a31SMat Martineau 
4646836be934SAndrei Emeltchenko 		chan->expected_tx_seq = __next_seq(chan, tx_seq);
46470a708f8fSGustavo F. Padovan 
464884084a31SMat Martineau 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
464984084a31SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
46500a708f8fSGustavo F. Padovan 
46510a708f8fSGustavo F. Padovan 		goto done;
46520a708f8fSGustavo F. Padovan 
46530a708f8fSGustavo F. Padovan 	default:
46540c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
46550a708f8fSGustavo F. Padovan 		break;
46560a708f8fSGustavo F. Padovan 	}
46570a708f8fSGustavo F. Padovan 
46580a708f8fSGustavo F. Padovan drop:
46590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46600a708f8fSGustavo F. Padovan 
46610a708f8fSGustavo F. Padovan done:
46626be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
46630a708f8fSGustavo F. Padovan 
46640a708f8fSGustavo F. Padovan 	return 0;
46650a708f8fSGustavo F. Padovan }
46660a708f8fSGustavo F. Padovan 
46670a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
46680a708f8fSGustavo F. Padovan {
466923691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46700a708f8fSGustavo F. Padovan 
4671c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
467223691d75SGustavo F. Padovan 	if (!chan)
46730a708f8fSGustavo F. Padovan 		goto drop;
46740a708f8fSGustavo F. Padovan 
46755b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
46760a708f8fSGustavo F. Padovan 
467789bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
46780a708f8fSGustavo F. Padovan 		goto drop;
46790a708f8fSGustavo F. Padovan 
4680e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
46810a708f8fSGustavo F. Padovan 		goto drop;
46820a708f8fSGustavo F. Padovan 
468323070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
46845b4cedaaSAndrei Emeltchenko 		return 0;
46850a708f8fSGustavo F. Padovan 
46860a708f8fSGustavo F. Padovan drop:
46870a708f8fSGustavo F. Padovan 	kfree_skb(skb);
46880a708f8fSGustavo F. Padovan 
46890a708f8fSGustavo F. Padovan 	return 0;
46900a708f8fSGustavo F. Padovan }
46910a708f8fSGustavo F. Padovan 
4692d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
4693d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
46949f69bda6SGustavo F. Padovan {
469523691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
46969f69bda6SGustavo F. Padovan 
4697c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
469823691d75SGustavo F. Padovan 	if (!chan)
46999f69bda6SGustavo F. Padovan 		goto drop;
47009f69bda6SGustavo F. Padovan 
47015b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
47029f69bda6SGustavo F. Padovan 
470389bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
47049f69bda6SGustavo F. Padovan 		goto drop;
47059f69bda6SGustavo F. Padovan 
4706e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
47079f69bda6SGustavo F. Padovan 		goto drop;
47089f69bda6SGustavo F. Padovan 
470923070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
47105b4cedaaSAndrei Emeltchenko 		return 0;
47119f69bda6SGustavo F. Padovan 
47129f69bda6SGustavo F. Padovan drop:
47139f69bda6SGustavo F. Padovan 	kfree_skb(skb);
47149f69bda6SGustavo F. Padovan 
47159f69bda6SGustavo F. Padovan 	return 0;
47169f69bda6SGustavo F. Padovan }
47179f69bda6SGustavo F. Padovan 
47180a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
47190a708f8fSGustavo F. Padovan {
47200a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
47210a708f8fSGustavo F. Padovan 	u16 cid, len;
47220a708f8fSGustavo F. Padovan 	__le16 psm;
47230a708f8fSGustavo F. Padovan 
47240a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
47250a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
47260a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
47270a708f8fSGustavo F. Padovan 
47280a708f8fSGustavo F. Padovan 	if (len != skb->len) {
47290a708f8fSGustavo F. Padovan 		kfree_skb(skb);
47300a708f8fSGustavo F. Padovan 		return;
47310a708f8fSGustavo F. Padovan 	}
47320a708f8fSGustavo F. Padovan 
47330a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
47340a708f8fSGustavo F. Padovan 
47350a708f8fSGustavo F. Padovan 	switch (cid) {
47363300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
47370a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
47380a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
47390a708f8fSGustavo F. Padovan 		break;
47400a708f8fSGustavo F. Padovan 
47410a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
4742097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
47430a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
47440a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
47450a708f8fSGustavo F. Padovan 		break;
47460a708f8fSGustavo F. Padovan 
47479f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
47489f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
47499f69bda6SGustavo F. Padovan 		break;
47509f69bda6SGustavo F. Padovan 
4751b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
4752b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
4753b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
4754b501d6a1SAnderson Briglia 		break;
4755b501d6a1SAnderson Briglia 
47560a708f8fSGustavo F. Padovan 	default:
47570a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
47580a708f8fSGustavo F. Padovan 		break;
47590a708f8fSGustavo F. Padovan 	}
47600a708f8fSGustavo F. Padovan }
47610a708f8fSGustavo F. Padovan 
47620a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
47630a708f8fSGustavo F. Padovan 
4764686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
47650a708f8fSGustavo F. Padovan {
47660a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
476723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
47680a708f8fSGustavo F. Padovan 
47690a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
47700a708f8fSGustavo F. Padovan 
47710a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
477223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
477323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
477423691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
47754343478fSGustavo F. Padovan 
477689bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
47770a708f8fSGustavo F. Padovan 			continue;
47780a708f8fSGustavo F. Padovan 
47790a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
47800a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
478143bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47820a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
47830a708f8fSGustavo F. Padovan 			exact++;
47840a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
47850a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
478643bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
47870a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
47880a708f8fSGustavo F. Padovan 		}
47890a708f8fSGustavo F. Padovan 	}
479023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
47910a708f8fSGustavo F. Padovan 
47920a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
47930a708f8fSGustavo F. Padovan }
47940a708f8fSGustavo F. Padovan 
4795686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
47960a708f8fSGustavo F. Padovan {
47970a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
47980a708f8fSGustavo F. Padovan 
47990a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
48000a708f8fSGustavo F. Padovan 
48010a708f8fSGustavo F. Padovan 	if (!status) {
48020a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
48030a708f8fSGustavo F. Padovan 		if (conn)
48040a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
48050a708f8fSGustavo F. Padovan 	} else
4806e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
48070a708f8fSGustavo F. Padovan 
48080a708f8fSGustavo F. Padovan 	return 0;
48090a708f8fSGustavo F. Padovan }
48100a708f8fSGustavo F. Padovan 
4811686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
48120a708f8fSGustavo F. Padovan {
48130a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
48140a708f8fSGustavo F. Padovan 
48150a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
48160a708f8fSGustavo F. Padovan 
4817686ebf28SUlisses Furquim 	if (!conn)
48189f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
48190a708f8fSGustavo F. Padovan 	return conn->disc_reason;
48200a708f8fSGustavo F. Padovan }
48210a708f8fSGustavo F. Padovan 
4822686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
48230a708f8fSGustavo F. Padovan {
48240a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
48250a708f8fSGustavo F. Padovan 
4826e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
48270a708f8fSGustavo F. Padovan 	return 0;
48280a708f8fSGustavo F. Padovan }
48290a708f8fSGustavo F. Padovan 
48304343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
48310a708f8fSGustavo F. Padovan {
4832715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
48330a708f8fSGustavo F. Padovan 		return;
48340a708f8fSGustavo F. Padovan 
48350a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
48364343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
4837ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
48384343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
48390f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
48400a708f8fSGustavo F. Padovan 	} else {
48414343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
4842c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
48430a708f8fSGustavo F. Padovan 	}
48440a708f8fSGustavo F. Padovan }
48450a708f8fSGustavo F. Padovan 
4846686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
48470a708f8fSGustavo F. Padovan {
48480a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
484948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
48500a708f8fSGustavo F. Padovan 
48510a708f8fSGustavo F. Padovan 	if (!conn)
48520a708f8fSGustavo F. Padovan 		return 0;
48530a708f8fSGustavo F. Padovan 
48540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
48550a708f8fSGustavo F. Padovan 
4856160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
485735d4adccSHemant Gupta 		if (!status && encrypt)
4858160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
485917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
4860160dc6acSVinicius Costa Gomes 	}
4861160dc6acSVinicius Costa Gomes 
48623df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
48630a708f8fSGustavo F. Padovan 
48643df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
48656be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
48660a708f8fSGustavo F. Padovan 
4867f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
4868f1cb9af5SVinicius Costa Gomes 
4869f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
4870f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
4871f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
4872cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
4873f1cb9af5SVinicius Costa Gomes 			}
4874f1cb9af5SVinicius Costa Gomes 
48756be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
4876f1cb9af5SVinicius Costa Gomes 			continue;
4877f1cb9af5SVinicius Costa Gomes 		}
4878f1cb9af5SVinicius Costa Gomes 
4879c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
48806be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48810a708f8fSGustavo F. Padovan 			continue;
48820a708f8fSGustavo F. Padovan 		}
48830a708f8fSGustavo F. Padovan 
488489bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
488589bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
48864343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
48876be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
48880a708f8fSGustavo F. Padovan 			continue;
48890a708f8fSGustavo F. Padovan 		}
48900a708f8fSGustavo F. Padovan 
489189bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
48920a708f8fSGustavo F. Padovan 			if (!status) {
48939b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
48940a708f8fSGustavo F. Padovan 			} else {
4895ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
48960a708f8fSGustavo F. Padovan 			}
489789bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
48986be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
48990a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
4900df3c3931SJohan Hedberg 			__u16 res, stat;
49010a708f8fSGustavo F. Padovan 
49026be36555SAndrei Emeltchenko 			lock_sock(sk);
49036be36555SAndrei Emeltchenko 
49040a708f8fSGustavo F. Padovan 			if (!status) {
4905df3c3931SJohan Hedberg 				if (bt_sk(sk)->defer_setup) {
4906df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
4907df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
4908df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
490905e9a2f6SIlia Kolomisnky 					if (parent)
4910df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
4911df3c3931SJohan Hedberg 				} else {
49120e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
4913df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
4914df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
4915df3c3931SJohan Hedberg 				}
49160a708f8fSGustavo F. Padovan 			} else {
49170e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
4918ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
4919df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
4920df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
49210a708f8fSGustavo F. Padovan 			}
49220a708f8fSGustavo F. Padovan 
49236be36555SAndrei Emeltchenko 			release_sock(sk);
49246be36555SAndrei Emeltchenko 
4925fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
4926fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
4927df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
4928df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
4929fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
4930fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
49310a708f8fSGustavo F. Padovan 		}
49320a708f8fSGustavo F. Padovan 
49336be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
49340a708f8fSGustavo F. Padovan 	}
49350a708f8fSGustavo F. Padovan 
49363df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
49370a708f8fSGustavo F. Padovan 
49380a708f8fSGustavo F. Padovan 	return 0;
49390a708f8fSGustavo F. Padovan }
49400a708f8fSGustavo F. Padovan 
4941686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
49420a708f8fSGustavo F. Padovan {
49430a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
49440a708f8fSGustavo F. Padovan 
49450a708f8fSGustavo F. Padovan 	if (!conn)
49460a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
49470a708f8fSGustavo F. Padovan 
49480a708f8fSGustavo F. Padovan 	if (!conn)
49490a708f8fSGustavo F. Padovan 		goto drop;
49500a708f8fSGustavo F. Padovan 
49510a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
49520a708f8fSGustavo F. Padovan 
49530a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
49540a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
495548454079SGustavo F. Padovan 		struct l2cap_chan *chan;
49560a708f8fSGustavo F. Padovan 		u16 cid;
49570a708f8fSGustavo F. Padovan 		int len;
49580a708f8fSGustavo F. Padovan 
49590a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
49600a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
49610a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
49620a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
49630a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
49640a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49650a708f8fSGustavo F. Padovan 		}
49660a708f8fSGustavo F. Padovan 
49670a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
49680a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
49690a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
49700a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49710a708f8fSGustavo F. Padovan 			goto drop;
49720a708f8fSGustavo F. Padovan 		}
49730a708f8fSGustavo F. Padovan 
49740a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
49750a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
49760a708f8fSGustavo F. Padovan 		cid = __le16_to_cpu(hdr->cid);
49770a708f8fSGustavo F. Padovan 
49780a708f8fSGustavo F. Padovan 		if (len == skb->len) {
49790a708f8fSGustavo F. Padovan 			/* Complete frame received */
49800a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
49810a708f8fSGustavo F. Padovan 			return 0;
49820a708f8fSGustavo F. Padovan 		}
49830a708f8fSGustavo F. Padovan 
49840a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
49850a708f8fSGustavo F. Padovan 
49860a708f8fSGustavo F. Padovan 		if (skb->len > len) {
49870a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
49880a708f8fSGustavo F. Padovan 				skb->len, len);
49890a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
49900a708f8fSGustavo F. Padovan 			goto drop;
49910a708f8fSGustavo F. Padovan 		}
49920a708f8fSGustavo F. Padovan 
4993baa7e1faSGustavo F. Padovan 		chan = l2cap_get_chan_by_scid(conn, cid);
49940a708f8fSGustavo F. Padovan 
499548454079SGustavo F. Padovan 		if (chan && chan->sk) {
499648454079SGustavo F. Padovan 			struct sock *sk = chan->sk;
49973df91ea2SAndrei Emeltchenko 			lock_sock(sk);
499848454079SGustavo F. Padovan 
49990c1bc5c6SGustavo F. Padovan 			if (chan->imtu < len - L2CAP_HDR_SIZE) {
500048454079SGustavo F. Padovan 				BT_ERR("Frame exceeding recv MTU (len %d, "
500148454079SGustavo F. Padovan 							"MTU %d)", len,
50020c1bc5c6SGustavo F. Padovan 							chan->imtu);
5003aa2ac881SGustavo F. Padovan 				release_sock(sk);
50040a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
50050a708f8fSGustavo F. Padovan 				goto drop;
50060a708f8fSGustavo F. Padovan 			}
5007aa2ac881SGustavo F. Padovan 			release_sock(sk);
500848454079SGustavo F. Padovan 		}
50090a708f8fSGustavo F. Padovan 
50100a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
50110a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
50120a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
50130a708f8fSGustavo F. Padovan 			goto drop;
50140a708f8fSGustavo F. Padovan 
50150a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50160a708f8fSGustavo F. Padovan 								skb->len);
50170a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
50180a708f8fSGustavo F. Padovan 	} else {
50190a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
50200a708f8fSGustavo F. Padovan 
50210a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50220a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
50230a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50240a708f8fSGustavo F. Padovan 			goto drop;
50250a708f8fSGustavo F. Padovan 		}
50260a708f8fSGustavo F. Padovan 
50270a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
50280a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
50290a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
50300a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
50310a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50320a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
50330a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
50340a708f8fSGustavo F. Padovan 			goto drop;
50350a708f8fSGustavo F. Padovan 		}
50360a708f8fSGustavo F. Padovan 
50370a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
50380a708f8fSGustavo F. Padovan 								skb->len);
50390a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
50400a708f8fSGustavo F. Padovan 
50410a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
50420a708f8fSGustavo F. Padovan 			/* Complete frame received */
50430a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
50440a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
50450a708f8fSGustavo F. Padovan 		}
50460a708f8fSGustavo F. Padovan 	}
50470a708f8fSGustavo F. Padovan 
50480a708f8fSGustavo F. Padovan drop:
50490a708f8fSGustavo F. Padovan 	kfree_skb(skb);
50500a708f8fSGustavo F. Padovan 	return 0;
50510a708f8fSGustavo F. Padovan }
50520a708f8fSGustavo F. Padovan 
50530a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
50540a708f8fSGustavo F. Padovan {
505523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
50560a708f8fSGustavo F. Padovan 
5057333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
50580a708f8fSGustavo F. Padovan 
505923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
506023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
50610a708f8fSGustavo F. Padovan 
5062903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
50630a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
50640a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
506589bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
506623691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
506723691d75SGustavo F. Padovan 					c->sec_level, c->mode);
50680a708f8fSGustavo F. Padovan 	}
50690a708f8fSGustavo F. Padovan 
5070333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
50710a708f8fSGustavo F. Padovan 
50720a708f8fSGustavo F. Padovan 	return 0;
50730a708f8fSGustavo F. Padovan }
50740a708f8fSGustavo F. Padovan 
50750a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
50760a708f8fSGustavo F. Padovan {
50770a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
50780a708f8fSGustavo F. Padovan }
50790a708f8fSGustavo F. Padovan 
50800a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
50810a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
50820a708f8fSGustavo F. Padovan 	.read		= seq_read,
50830a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
50840a708f8fSGustavo F. Padovan 	.release	= single_release,
50850a708f8fSGustavo F. Padovan };
50860a708f8fSGustavo F. Padovan 
50870a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
50880a708f8fSGustavo F. Padovan 
508964274518SGustavo F. Padovan int __init l2cap_init(void)
50900a708f8fSGustavo F. Padovan {
50910a708f8fSGustavo F. Padovan 	int err;
50920a708f8fSGustavo F. Padovan 
5093bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
50940a708f8fSGustavo F. Padovan 	if (err < 0)
50950a708f8fSGustavo F. Padovan 		return err;
50960a708f8fSGustavo F. Padovan 
50970a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
50980a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
50990a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
51000a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
51010a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
51020a708f8fSGustavo F. Padovan 	}
51030a708f8fSGustavo F. Padovan 
51040a708f8fSGustavo F. Padovan 	return 0;
51050a708f8fSGustavo F. Padovan }
51060a708f8fSGustavo F. Padovan 
510764274518SGustavo F. Padovan void l2cap_exit(void)
51080a708f8fSGustavo F. Padovan {
51090a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5110bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
51110a708f8fSGustavo F. Padovan }
51120a708f8fSGustavo F. Padovan 
51130a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
51140a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5115