xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 30648372)
10a708f8fSGustavo F. Padovan /*
20a708f8fSGustavo F. Padovan    BlueZ - Bluetooth protocol stack for Linux
30a708f8fSGustavo F. Padovan    Copyright (C) 2000-2001 Qualcomm Incorporated
40a708f8fSGustavo F. Padovan    Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
50a708f8fSGustavo F. Padovan    Copyright (C) 2010 Google Inc.
6590051deSGustavo F. Padovan    Copyright (C) 2011 ProFUSION Embedded Systems
7422e925bSMat Martineau    Copyright (c) 2012 Code Aurora Forum.  All rights reserved.
80a708f8fSGustavo F. Padovan 
90a708f8fSGustavo F. Padovan    Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
100a708f8fSGustavo F. Padovan 
110a708f8fSGustavo F. Padovan    This program is free software; you can redistribute it and/or modify
120a708f8fSGustavo F. Padovan    it under the terms of the GNU General Public License version 2 as
130a708f8fSGustavo F. Padovan    published by the Free Software Foundation;
140a708f8fSGustavo F. Padovan 
150a708f8fSGustavo F. Padovan    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
160a708f8fSGustavo F. Padovan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170a708f8fSGustavo F. Padovan    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
180a708f8fSGustavo F. Padovan    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
190a708f8fSGustavo F. Padovan    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
200a708f8fSGustavo F. Padovan    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
210a708f8fSGustavo F. Padovan    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
220a708f8fSGustavo F. Padovan    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
230a708f8fSGustavo F. Padovan 
240a708f8fSGustavo F. Padovan    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
250a708f8fSGustavo F. Padovan    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
260a708f8fSGustavo F. Padovan    SOFTWARE IS DISCLAIMED.
270a708f8fSGustavo F. Padovan */
280a708f8fSGustavo F. Padovan 
29bb58f747SGustavo F. Padovan /* Bluetooth L2CAP core. */
300a708f8fSGustavo F. Padovan 
310a708f8fSGustavo F. Padovan #include <linux/module.h>
320a708f8fSGustavo F. Padovan 
330a708f8fSGustavo F. Padovan #include <linux/debugfs.h>
340a708f8fSGustavo F. Padovan #include <linux/crc16.h>
350a708f8fSGustavo F. Padovan 
360a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
370a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
380a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
39b501d6a1SAnderson Briglia #include <net/bluetooth/smp.h>
4097e8e89dSAndrei Emeltchenko #include <net/bluetooth/a2mp.h>
410a708f8fSGustavo F. Padovan 
42d1de6d46SMat Martineau bool disable_ertm;
430a708f8fSGustavo F. Padovan 
440a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
4550a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
460a708f8fSGustavo F. Padovan 
47b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
48b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
490a708f8fSGustavo F. Padovan 
500a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
510a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
524519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
534519de9aSGustavo F. Padovan 								void *data);
54710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
554519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
564519de9aSGustavo F. Padovan 				   struct l2cap_chan *chan, int err);
570a708f8fSGustavo F. Padovan 
58d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
59608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event);
60608bcc6dSMat Martineau 
610a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
6271ba0e56SGustavo F. Padovan 
63baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
640a708f8fSGustavo F. Padovan {
653df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
66baa7e1faSGustavo F. Padovan 
673df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
683df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
693df91ea2SAndrei Emeltchenko 			return c;
700a708f8fSGustavo F. Padovan 	}
713df91ea2SAndrei Emeltchenko 	return NULL;
72baa7e1faSGustavo F. Padovan }
730a708f8fSGustavo F. Padovan 
74baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
750a708f8fSGustavo F. Padovan {
763df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
77baa7e1faSGustavo F. Padovan 
783df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
793df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
803df91ea2SAndrei Emeltchenko 			return c;
810a708f8fSGustavo F. Padovan 	}
823df91ea2SAndrei Emeltchenko 	return NULL;
83baa7e1faSGustavo F. Padovan }
840a708f8fSGustavo F. Padovan 
850a708f8fSGustavo F. Padovan /* Find channel with given SCID.
86ef191adeSMat Martineau  * Returns locked channel. */
87baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
880a708f8fSGustavo F. Padovan {
8948454079SGustavo F. Padovan 	struct l2cap_chan *c;
90baa7e1faSGustavo F. Padovan 
913df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
92baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
93ef191adeSMat Martineau 	if (c)
94ef191adeSMat Martineau 		l2cap_chan_lock(c);
953df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
963df91ea2SAndrei Emeltchenko 
9748454079SGustavo F. Padovan 	return c;
980a708f8fSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
100baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1010a708f8fSGustavo F. Padovan {
1023df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
103baa7e1faSGustavo F. Padovan 
1043df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1053df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1063df91ea2SAndrei Emeltchenko 			return c;
1070a708f8fSGustavo F. Padovan 	}
1083df91ea2SAndrei Emeltchenko 	return NULL;
109baa7e1faSGustavo F. Padovan }
1100a708f8fSGustavo F. Padovan 
11123691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1129e4425ffSGustavo F. Padovan {
11323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1149e4425ffSGustavo F. Padovan 
11523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
11623691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
11723691d75SGustavo F. Padovan 			return c;
1189e4425ffSGustavo F. Padovan 	}
119250938cbSSzymon Janc 	return NULL;
120250938cbSSzymon Janc }
1219e4425ffSGustavo F. Padovan 
1229e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1239e4425ffSGustavo F. Padovan {
12473b2ec18SGustavo F. Padovan 	int err;
12573b2ec18SGustavo F. Padovan 
126333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1279e4425ffSGustavo F. Padovan 
12823691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
12973b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
13073b2ec18SGustavo F. Padovan 		goto done;
1319e4425ffSGustavo F. Padovan 	}
1329e4425ffSGustavo F. Padovan 
13373b2ec18SGustavo F. Padovan 	if (psm) {
1349e4425ffSGustavo F. Padovan 		chan->psm = psm;
1359e4425ffSGustavo F. Padovan 		chan->sport = psm;
13673b2ec18SGustavo F. Padovan 		err = 0;
13773b2ec18SGustavo F. Padovan 	} else {
13873b2ec18SGustavo F. Padovan 		u16 p;
1399e4425ffSGustavo F. Padovan 
14073b2ec18SGustavo F. Padovan 		err = -EINVAL;
14173b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
14223691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
14373b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
14473b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
14573b2ec18SGustavo F. Padovan 				err = 0;
14673b2ec18SGustavo F. Padovan 				break;
14773b2ec18SGustavo F. Padovan 			}
14873b2ec18SGustavo F. Padovan 	}
14973b2ec18SGustavo F. Padovan 
15073b2ec18SGustavo F. Padovan done:
151333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
15273b2ec18SGustavo F. Padovan 	return err;
1539e4425ffSGustavo F. Padovan }
1549e4425ffSGustavo F. Padovan 
1559e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1569e4425ffSGustavo F. Padovan {
157333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1589e4425ffSGustavo F. Padovan 
1599e4425ffSGustavo F. Padovan 	chan->scid = scid;
1609e4425ffSGustavo F. Padovan 
161333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1629e4425ffSGustavo F. Padovan 
1639e4425ffSGustavo F. Padovan 	return 0;
1649e4425ffSGustavo F. Padovan }
1659e4425ffSGustavo F. Padovan 
166baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1670a708f8fSGustavo F. Padovan {
1680a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1690a708f8fSGustavo F. Padovan 
1700a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
171baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1720a708f8fSGustavo F. Padovan 			return cid;
1730a708f8fSGustavo F. Padovan 	}
1740a708f8fSGustavo F. Padovan 
1750a708f8fSGustavo F. Padovan 	return 0;
1760a708f8fSGustavo F. Padovan }
1770a708f8fSGustavo F. Padovan 
1780e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
17989bc500eSGustavo F. Padovan {
18042d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
181badaaa00SGustavo F. Padovan 						state_to_string(state));
182badaaa00SGustavo F. Padovan 
18389bc500eSGustavo F. Padovan 	chan->state = state;
18480b98027SGustavo Padovan 	chan->ops->state_change(chan, state);
18589bc500eSGustavo F. Padovan }
18689bc500eSGustavo F. Padovan 
1870e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
1880e587be7SAndrei Emeltchenko {
1890e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
1900e587be7SAndrei Emeltchenko 
1910e587be7SAndrei Emeltchenko 	lock_sock(sk);
1920e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
1930e587be7SAndrei Emeltchenko 	release_sock(sk);
1940e587be7SAndrei Emeltchenko }
1950e587be7SAndrei Emeltchenko 
1962e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
1972e0052e4SAndrei Emeltchenko {
1982e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
1992e0052e4SAndrei Emeltchenko 
2002e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2012e0052e4SAndrei Emeltchenko }
2022e0052e4SAndrei Emeltchenko 
2032e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2042e0052e4SAndrei Emeltchenko {
2052e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2062e0052e4SAndrei Emeltchenko 
2072e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2082e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2092e0052e4SAndrei Emeltchenko 	release_sock(sk);
2102e0052e4SAndrei Emeltchenko }
2112e0052e4SAndrei Emeltchenko 
2124239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2134239d16fSMat Martineau {
2144239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2154239d16fSMat Martineau 	    chan->retrans_timeout) {
2164239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2174239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2184239d16fSMat Martineau 	}
2194239d16fSMat Martineau }
2204239d16fSMat Martineau 
2214239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2224239d16fSMat Martineau {
2234239d16fSMat Martineau 	__clear_retrans_timer(chan);
2244239d16fSMat Martineau 	if (chan->monitor_timeout) {
2254239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2264239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2274239d16fSMat Martineau 	}
2284239d16fSMat Martineau }
2294239d16fSMat Martineau 
230608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
231608bcc6dSMat Martineau 					       u16 seq)
232608bcc6dSMat Martineau {
233608bcc6dSMat Martineau 	struct sk_buff *skb;
234608bcc6dSMat Martineau 
235608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
236608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
237608bcc6dSMat Martineau 			return skb;
238608bcc6dSMat Martineau 	}
239608bcc6dSMat Martineau 
240608bcc6dSMat Martineau 	return NULL;
241608bcc6dSMat Martineau }
242608bcc6dSMat Martineau 
2433c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2443c588192SMat Martineau 
2453c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2463c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2473c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2483c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2493c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2503c588192SMat Martineau  * and removed from the head in constant time, without further memory
2513c588192SMat Martineau  * allocs or frees.
2523c588192SMat Martineau  */
2533c588192SMat Martineau 
2543c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2553c588192SMat Martineau {
2563c588192SMat Martineau 	size_t alloc_size, i;
2573c588192SMat Martineau 
2583c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2593c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2603c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2613c588192SMat Martineau 	 */
2623c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2633c588192SMat Martineau 
2643c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2653c588192SMat Martineau 	if (!seq_list->list)
2663c588192SMat Martineau 		return -ENOMEM;
2673c588192SMat Martineau 
2683c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2693c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2703c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2713c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2723c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2733c588192SMat Martineau 
2743c588192SMat Martineau 	return 0;
2753c588192SMat Martineau }
2763c588192SMat Martineau 
2773c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2783c588192SMat Martineau {
2793c588192SMat Martineau 	kfree(seq_list->list);
2803c588192SMat Martineau }
2813c588192SMat Martineau 
2823c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2833c588192SMat Martineau 					   u16 seq)
2843c588192SMat Martineau {
2853c588192SMat Martineau 	/* Constant-time check for list membership */
2863c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2873c588192SMat Martineau }
2883c588192SMat Martineau 
2893c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2903c588192SMat Martineau {
2913c588192SMat Martineau 	u16 mask = seq_list->mask;
2923c588192SMat Martineau 
2933c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2943c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2953c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2963c588192SMat Martineau 	} else if (seq_list->head == seq) {
2973c588192SMat Martineau 		/* Head can be removed in constant time */
2983c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2993c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3003c588192SMat Martineau 
3013c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3023c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3033c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3043c588192SMat Martineau 		}
3053c588192SMat Martineau 	} else {
3063c588192SMat Martineau 		/* Walk the list to find the sequence number */
3073c588192SMat Martineau 		u16 prev = seq_list->head;
3083c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3093c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3103c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3113c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3123c588192SMat Martineau 		}
3133c588192SMat Martineau 
3143c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3153c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3163c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3173c588192SMat Martineau 		if (seq_list->tail == seq)
3183c588192SMat Martineau 			seq_list->tail = prev;
3193c588192SMat Martineau 	}
3203c588192SMat Martineau 	return seq;
3213c588192SMat Martineau }
3223c588192SMat Martineau 
3233c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3243c588192SMat Martineau {
3253c588192SMat Martineau 	/* Remove the head in constant time */
3263c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3273c588192SMat Martineau }
3283c588192SMat Martineau 
3293c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3303c588192SMat Martineau {
3313c588192SMat Martineau 	u16 i;
332f522ae36SGustavo Padovan 
333f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
334f522ae36SGustavo Padovan 		return;
335f522ae36SGustavo Padovan 
3363c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3373c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3383c588192SMat Martineau 
3393c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3413c588192SMat Martineau }
3423c588192SMat Martineau 
3433c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3443c588192SMat Martineau {
3453c588192SMat Martineau 	u16 mask = seq_list->mask;
3463c588192SMat Martineau 
3473c588192SMat Martineau 	/* All appends happen in constant time */
3483c588192SMat Martineau 
349f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
350f522ae36SGustavo Padovan 		return;
351f522ae36SGustavo Padovan 
3523c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3533c588192SMat Martineau 		seq_list->head = seq;
3543c588192SMat Martineau 	else
3553c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3563c588192SMat Martineau 
3573c588192SMat Martineau 	seq_list->tail = seq;
3583c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3593c588192SMat Martineau }
3603c588192SMat Martineau 
361721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
362ab07801dSGustavo F. Padovan {
363721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
364721c4181SGustavo F. Padovan 							chan_timer.work);
3653df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
366ab07801dSGustavo F. Padovan 	int reason;
367ab07801dSGustavo F. Padovan 
368e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
369ab07801dSGustavo F. Padovan 
3703df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3716be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
372ab07801dSGustavo F. Padovan 
37389bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
374ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
37589bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
376ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
377ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
378ab07801dSGustavo F. Padovan 	else
379ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
380ab07801dSGustavo F. Padovan 
3810f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
382ab07801dSGustavo F. Padovan 
3836be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
384ab07801dSGustavo F. Padovan 
38580b98027SGustavo Padovan 	chan->ops->close(chan);
3863df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3873df91ea2SAndrei Emeltchenko 
388371fd835SUlisses Furquim 	l2cap_chan_put(chan);
389ab07801dSGustavo F. Padovan }
390ab07801dSGustavo F. Padovan 
391eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3920a708f8fSGustavo F. Padovan {
39348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3940a708f8fSGustavo F. Padovan 
39548454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
39648454079SGustavo F. Padovan 	if (!chan)
39748454079SGustavo F. Padovan 		return NULL;
3980a708f8fSGustavo F. Padovan 
399c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
400c03b355eSAndrei Emeltchenko 
401333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40223691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
403333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40423691d75SGustavo F. Padovan 
405721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
406ab07801dSGustavo F. Padovan 
40789bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
40889bc500eSGustavo F. Padovan 
40971ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
41071ba0e56SGustavo F. Padovan 
4112827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4122827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4132827011fSMat Martineau 
414eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
415abc545b8SSzymon Janc 
41648454079SGustavo F. Padovan 	return chan;
4170a708f8fSGustavo F. Padovan }
4180a708f8fSGustavo F. Padovan 
41923691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4206ff5abbfSGustavo F. Padovan {
421333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
42223691d75SGustavo F. Padovan 	list_del(&chan->global_l);
423333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
42423691d75SGustavo F. Padovan 
425371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4266ff5abbfSGustavo F. Padovan }
4276ff5abbfSGustavo F. Padovan 
428*30648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
429*30648372SJaganath Kanakkassery {
430*30648372SJaganath Kanakkassery 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
431*30648372SJaganath Kanakkassery 
432*30648372SJaganath Kanakkassery 	atomic_inc(&c->refcnt);
433*30648372SJaganath Kanakkassery }
434*30648372SJaganath Kanakkassery 
435*30648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
436*30648372SJaganath Kanakkassery {
437*30648372SJaganath Kanakkassery 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
438*30648372SJaganath Kanakkassery 
439*30648372SJaganath Kanakkassery 	if (atomic_dec_and_test(&c->refcnt))
440*30648372SJaganath Kanakkassery 		kfree(c);
441*30648372SJaganath Kanakkassery }
442*30648372SJaganath Kanakkassery 
443bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
444bd4b1653SAndrei Emeltchenko {
445bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
446bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
447bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
448bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
449c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
450bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
451bd4b1653SAndrei Emeltchenko 
452bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
453bd4b1653SAndrei Emeltchenko }
454bd4b1653SAndrei Emeltchenko 
45514a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4560a708f8fSGustavo F. Padovan {
4570a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
458097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4590a708f8fSGustavo F. Padovan 
4609f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4610a708f8fSGustavo F. Padovan 
4628c1d787bSGustavo F. Padovan 	chan->conn = conn;
4630a708f8fSGustavo F. Padovan 
4645491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4655491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
466b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
467b62f328bSVille Tervo 			/* LE connection */
4686fcb06a2SAndre Guedes 			chan->omtu = L2CAP_DEFAULT_MTU;
469fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
470fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
471b62f328bSVille Tervo 		} else {
4720a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
473fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4740c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
475b62f328bSVille Tervo 		}
4765491120eSAndrei Emeltchenko 		break;
4775491120eSAndrei Emeltchenko 
4785491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4790a708f8fSGustavo F. Padovan 		/* Connectionless socket */
480fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
481fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4820c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4835491120eSAndrei Emeltchenko 		break;
4845491120eSAndrei Emeltchenko 
485416fa752SAndrei Emeltchenko 	case L2CAP_CHAN_CONN_FIX_A2MP:
486416fa752SAndrei Emeltchenko 		chan->scid = L2CAP_CID_A2MP;
487416fa752SAndrei Emeltchenko 		chan->dcid = L2CAP_CID_A2MP;
488416fa752SAndrei Emeltchenko 		chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
489416fa752SAndrei Emeltchenko 		chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
490416fa752SAndrei Emeltchenko 		break;
491416fa752SAndrei Emeltchenko 
4925491120eSAndrei Emeltchenko 	default:
4930a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
494fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
495fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4960c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4970a708f8fSGustavo F. Padovan 	}
4980a708f8fSGustavo F. Padovan 
4998f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5008f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5018f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5028f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5038f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5048f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
5058f7975b1SAndrei Emeltchenko 
506371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
507baa7e1faSGustavo F. Padovan 
5083df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
509643162a8SAndrei Emeltchenko }
510643162a8SAndrei Emeltchenko 
511466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
512643162a8SAndrei Emeltchenko {
513643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
514643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5153df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5160a708f8fSGustavo F. Padovan }
5170a708f8fSGustavo F. Padovan 
518466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5190a708f8fSGustavo F. Padovan {
5208c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5210a708f8fSGustavo F. Padovan 
522c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5230a708f8fSGustavo F. Padovan 
52449208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5250a708f8fSGustavo F. Padovan 
5260a708f8fSGustavo F. Padovan 	if (conn) {
527baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5283df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5293d57dc68SGustavo F. Padovan 
530371fd835SUlisses Furquim 		l2cap_chan_put(chan);
531baa7e1faSGustavo F. Padovan 
5328c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5333cabbfdaSAndrei Emeltchenko 
5343cabbfdaSAndrei Emeltchenko 		if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
5350a708f8fSGustavo F. Padovan 			hci_conn_put(conn->hcon);
5360a708f8fSGustavo F. Padovan 	}
5370a708f8fSGustavo F. Padovan 
538c0df7f6eSAndrei Emeltchenko 	if (chan->ops->teardown)
539c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, err);
5406be36555SAndrei Emeltchenko 
5412827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
5426ff5abbfSGustavo F. Padovan 		return;
5432ead70b8SGustavo F. Padovan 
544ee556f66SGustavo Padovan 	switch(chan->mode) {
545ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
546ee556f66SGustavo Padovan 		break;
5470a708f8fSGustavo F. Padovan 
548ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
5491a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5501a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5511a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5520a708f8fSGustavo F. Padovan 
553f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5540a708f8fSGustavo F. Padovan 
5553c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5563c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
557ee556f66SGustavo Padovan 
558ee556f66SGustavo Padovan 		/* fall through */
559ee556f66SGustavo Padovan 
560ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
561ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
562ee556f66SGustavo Padovan 		break;
5630a708f8fSGustavo F. Padovan 	}
564ee556f66SGustavo Padovan 
565ee556f66SGustavo Padovan 	return;
5660a708f8fSGustavo F. Padovan }
5670a708f8fSGustavo F. Padovan 
5680f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5694519de9aSGustavo F. Padovan {
5704519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5714519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5724519de9aSGustavo F. Padovan 
573e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
574e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5754519de9aSGustavo F. Padovan 
57689bc500eSGustavo F. Padovan 	switch (chan->state) {
5774519de9aSGustavo F. Padovan 	case BT_LISTEN:
578c0df7f6eSAndrei Emeltchenko 		if (chan->ops->teardown)
579c0df7f6eSAndrei Emeltchenko 			chan->ops->teardown(chan, 0);
5804519de9aSGustavo F. Padovan 		break;
5814519de9aSGustavo F. Padovan 
5824519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5834519de9aSGustavo F. Padovan 	case BT_CONFIG:
584715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5854519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
586c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5874519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
5884519de9aSGustavo F. Padovan 		} else
5894519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
5904519de9aSGustavo F. Padovan 		break;
5914519de9aSGustavo F. Padovan 
5924519de9aSGustavo F. Padovan 	case BT_CONNECT2:
593715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5944519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
5954519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5964519de9aSGustavo F. Padovan 			__u16 result;
5974519de9aSGustavo F. Padovan 
598c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
5994519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
6004519de9aSGustavo F. Padovan 			else
6014519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
60289bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
6034519de9aSGustavo F. Padovan 
6044519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6054519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6064519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
607ac73498cSAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
6084519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6094519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6104519de9aSGustavo F. Padovan 		}
6114519de9aSGustavo F. Padovan 
6124519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6134519de9aSGustavo F. Padovan 		break;
6144519de9aSGustavo F. Padovan 
6154519de9aSGustavo F. Padovan 	case BT_CONNECT:
6164519de9aSGustavo F. Padovan 	case BT_DISCONN:
6174519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6184519de9aSGustavo F. Padovan 		break;
6194519de9aSGustavo F. Padovan 
6204519de9aSGustavo F. Padovan 	default:
621c0df7f6eSAndrei Emeltchenko 		if (chan->ops->teardown)
622c0df7f6eSAndrei Emeltchenko 			chan->ops->teardown(chan, 0);
6234519de9aSGustavo F. Padovan 		break;
6244519de9aSGustavo F. Padovan 	}
6254519de9aSGustavo F. Padovan }
6264519de9aSGustavo F. Padovan 
6274343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6280a708f8fSGustavo F. Padovan {
629715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6304343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6310a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6320a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6330a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6340a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6350a708f8fSGustavo F. Padovan 		default:
6360a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6370a708f8fSGustavo F. Padovan 		}
6382983fd68SAndrei Emeltchenko 	} else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
6394343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6404343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6410a708f8fSGustavo F. Padovan 
6424343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6430a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6440a708f8fSGustavo F. Padovan 		else
6450a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6460a708f8fSGustavo F. Padovan 	} else {
6474343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6480a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6490a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6500a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6510a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6520a708f8fSGustavo F. Padovan 		default:
6530a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6540a708f8fSGustavo F. Padovan 		}
6550a708f8fSGustavo F. Padovan 	}
6560a708f8fSGustavo F. Padovan }
6570a708f8fSGustavo F. Padovan 
6580a708f8fSGustavo F. Padovan /* Service level security */
659d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6600a708f8fSGustavo F. Padovan {
6618c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6620a708f8fSGustavo F. Padovan 	__u8 auth_type;
6630a708f8fSGustavo F. Padovan 
6644343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6650a708f8fSGustavo F. Padovan 
6664343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6670a708f8fSGustavo F. Padovan }
6680a708f8fSGustavo F. Padovan 
669b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6700a708f8fSGustavo F. Padovan {
6710a708f8fSGustavo F. Padovan 	u8 id;
6720a708f8fSGustavo F. Padovan 
6730a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6740a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6750a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6760a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6770a708f8fSGustavo F. Padovan 	 */
6780a708f8fSGustavo F. Padovan 
679333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6800a708f8fSGustavo F. Padovan 
6810a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6820a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6830a708f8fSGustavo F. Padovan 
6840a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6850a708f8fSGustavo F. Padovan 
686333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
6870a708f8fSGustavo F. Padovan 
6880a708f8fSGustavo F. Padovan 	return id;
6890a708f8fSGustavo F. Padovan }
6900a708f8fSGustavo F. Padovan 
6914519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
6920a708f8fSGustavo F. Padovan {
6930a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
6940a708f8fSGustavo F. Padovan 	u8 flags;
6950a708f8fSGustavo F. Padovan 
6960a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
6970a708f8fSGustavo F. Padovan 
6980a708f8fSGustavo F. Padovan 	if (!skb)
6990a708f8fSGustavo F. Padovan 		return;
7000a708f8fSGustavo F. Padovan 
7010a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
7020a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
7030a708f8fSGustavo F. Padovan 	else
7040a708f8fSGustavo F. Padovan 		flags = ACL_START;
7050a708f8fSGustavo F. Padovan 
70614b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7075e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
70814b12d0bSJaikumar Ganesh 
70973d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7100a708f8fSGustavo F. Padovan }
7110a708f8fSGustavo F. Padovan 
71273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
71373d80debSLuiz Augusto von Dentz {
71473d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
71573d80debSLuiz Augusto von Dentz 	u16 flags;
71673d80debSLuiz Augusto von Dentz 
71773d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
71873d80debSLuiz Augusto von Dentz 							skb->priority);
71973d80debSLuiz Augusto von Dentz 
72073d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
72173d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
72273d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
72373d80debSLuiz Augusto von Dentz 	else
72473d80debSLuiz Augusto von Dentz 		flags = ACL_START;
72573d80debSLuiz Augusto von Dentz 
72673d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
72773d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7280a708f8fSGustavo F. Padovan }
7290a708f8fSGustavo F. Padovan 
730b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
731b5c6aaedSMat Martineau {
732b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
733b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
734b5c6aaedSMat Martineau 
735b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
736b5c6aaedSMat Martineau 		/* S-Frame */
737b5c6aaedSMat Martineau 		control->sframe = 1;
738b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
739b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
740b5c6aaedSMat Martineau 
741b5c6aaedSMat Martineau 		control->sar = 0;
742b5c6aaedSMat Martineau 		control->txseq = 0;
743b5c6aaedSMat Martineau 	} else {
744b5c6aaedSMat Martineau 		/* I-Frame */
745b5c6aaedSMat Martineau 		control->sframe = 0;
746b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
747b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
748b5c6aaedSMat Martineau 
749b5c6aaedSMat Martineau 		control->poll = 0;
750b5c6aaedSMat Martineau 		control->super = 0;
751b5c6aaedSMat Martineau 	}
752b5c6aaedSMat Martineau }
753b5c6aaedSMat Martineau 
754b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
755b5c6aaedSMat Martineau {
756b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
757b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
758b5c6aaedSMat Martineau 
759b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
760b5c6aaedSMat Martineau 		/* S-Frame */
761b5c6aaedSMat Martineau 		control->sframe = 1;
762b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
763b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
764b5c6aaedSMat Martineau 
765b5c6aaedSMat Martineau 		control->sar = 0;
766b5c6aaedSMat Martineau 		control->txseq = 0;
767b5c6aaedSMat Martineau 	} else {
768b5c6aaedSMat Martineau 		/* I-Frame */
769b5c6aaedSMat Martineau 		control->sframe = 0;
770b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
771b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
772b5c6aaedSMat Martineau 
773b5c6aaedSMat Martineau 		control->poll = 0;
774b5c6aaedSMat Martineau 		control->super = 0;
775b5c6aaedSMat Martineau 	}
776b5c6aaedSMat Martineau }
777b5c6aaedSMat Martineau 
778b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
779b5c6aaedSMat Martineau 				    struct sk_buff *skb)
780b5c6aaedSMat Martineau {
781b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
782b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
783b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
784cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
785b5c6aaedSMat Martineau 	} else {
786b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
787b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
788cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
789b5c6aaedSMat Martineau 	}
790b5c6aaedSMat Martineau }
791b5c6aaedSMat Martineau 
792b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
793b5c6aaedSMat Martineau {
794b5c6aaedSMat Martineau 	u32 packed;
795b5c6aaedSMat Martineau 
796b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
797b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
798b5c6aaedSMat Martineau 
799b5c6aaedSMat Martineau 	if (control->sframe) {
800b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
801b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
802b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
803b5c6aaedSMat Martineau 	} else {
804b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
805b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
806b5c6aaedSMat Martineau 	}
807b5c6aaedSMat Martineau 
808b5c6aaedSMat Martineau 	return packed;
809b5c6aaedSMat Martineau }
810b5c6aaedSMat Martineau 
811b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
812b5c6aaedSMat Martineau {
813b5c6aaedSMat Martineau 	u16 packed;
814b5c6aaedSMat Martineau 
815b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
816b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
817b5c6aaedSMat Martineau 
818b5c6aaedSMat Martineau 	if (control->sframe) {
819b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
820b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
821b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
822b5c6aaedSMat Martineau 	} else {
823b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
824b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
825b5c6aaedSMat Martineau 	}
826b5c6aaedSMat Martineau 
827b5c6aaedSMat Martineau 	return packed;
828b5c6aaedSMat Martineau }
829b5c6aaedSMat Martineau 
830b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
831b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
832b5c6aaedSMat Martineau 				  struct sk_buff *skb)
833b5c6aaedSMat Martineau {
834b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
835b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
836b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
837b5c6aaedSMat Martineau 	} else {
838b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
839b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
840b5c6aaedSMat Martineau 	}
841b5c6aaedSMat Martineau }
842b5c6aaedSMat Martineau 
843ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
844ba7aa64fSGustavo Padovan {
845ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
846ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
847ba7aa64fSGustavo Padovan 	else
848ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
849ba7aa64fSGustavo Padovan }
850ba7aa64fSGustavo Padovan 
851a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
852a67d7f6fSMat Martineau 					       u32 control)
8530a708f8fSGustavo F. Padovan {
8540a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8550a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
856ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
8570a708f8fSGustavo F. Padovan 
8580a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
85903a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8600a708f8fSGustavo F. Padovan 
861a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
8620a708f8fSGustavo F. Padovan 
8630a708f8fSGustavo F. Padovan 	if (!skb)
864a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
8650a708f8fSGustavo F. Padovan 
8660a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8670a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
868fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
86988843ab0SAndrei Emeltchenko 
870a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
871a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
872a67d7f6fSMat Martineau 	else
873a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
8740a708f8fSGustavo F. Padovan 
87547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
876a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
87703a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8780a708f8fSGustavo F. Padovan 	}
8790a708f8fSGustavo F. Padovan 
88073d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
881a67d7f6fSMat Martineau 	return skb;
882a67d7f6fSMat Martineau }
883a67d7f6fSMat Martineau 
884a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
885a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
886a67d7f6fSMat Martineau {
887a67d7f6fSMat Martineau 	struct sk_buff *skb;
888a67d7f6fSMat Martineau 	u32 control_field;
889a67d7f6fSMat Martineau 
890a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
891a67d7f6fSMat Martineau 
892a67d7f6fSMat Martineau 	if (!control->sframe)
893a67d7f6fSMat Martineau 		return;
894a67d7f6fSMat Martineau 
895a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
896a67d7f6fSMat Martineau 	    !control->poll)
897a67d7f6fSMat Martineau 		control->final = 1;
898a67d7f6fSMat Martineau 
899a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
900a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
901a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
902a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
903a67d7f6fSMat Martineau 
904a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
905a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
906a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
907a67d7f6fSMat Martineau 	}
908a67d7f6fSMat Martineau 
909a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
910a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
911a67d7f6fSMat Martineau 
912a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
913a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
914a67d7f6fSMat Martineau 	else
915a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
916a67d7f6fSMat Martineau 
917a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
918a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
91973d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
9200a708f8fSGustavo F. Padovan }
9210a708f8fSGustavo F. Padovan 
922c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
9230a708f8fSGustavo F. Padovan {
924c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
9250a708f8fSGustavo F. Padovan 
926c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
927c9e3d5e0SMat Martineau 
928c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
929c9e3d5e0SMat Martineau 	control.sframe = 1;
930c9e3d5e0SMat Martineau 	control.poll = poll;
931c9e3d5e0SMat Martineau 
932c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
933c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
934c9e3d5e0SMat Martineau 	else
935c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
936c9e3d5e0SMat Martineau 
937c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
938c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
9390a708f8fSGustavo F. Padovan }
9400a708f8fSGustavo F. Padovan 
941b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9420a708f8fSGustavo F. Padovan {
943c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9440a708f8fSGustavo F. Padovan }
9450a708f8fSGustavo F. Padovan 
9469b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9479b27f350SAndrei Emeltchenko {
9489b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9499b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9509b27f350SAndrei Emeltchenko 
9519b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9529b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9539b27f350SAndrei Emeltchenko 
9549b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9559b27f350SAndrei Emeltchenko 
9569b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9579b27f350SAndrei Emeltchenko 
9589b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9599b27f350SAndrei Emeltchenko }
9609b27f350SAndrei Emeltchenko 
9619f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9629f0caeb1SVinicius Costa Gomes {
9632827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9649f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9659f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9669f0caeb1SVinicius Costa Gomes 
96754a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
9689f0caeb1SVinicius Costa Gomes 
96954a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
9709f0caeb1SVinicius Costa Gomes }
9719f0caeb1SVinicius Costa Gomes 
972fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9730a708f8fSGustavo F. Padovan {
9748c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9750a708f8fSGustavo F. Padovan 
9769f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
9779f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
9789f0caeb1SVinicius Costa Gomes 		return;
9799f0caeb1SVinicius Costa Gomes 	}
9809f0caeb1SVinicius Costa Gomes 
9810a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
9820a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
9830a708f8fSGustavo F. Padovan 			return;
9840a708f8fSGustavo F. Padovan 
985d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
9869b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
9879b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
9880a708f8fSGustavo F. Padovan 	} else {
9890a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
990ac73498cSAndrei Emeltchenko 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
9910a708f8fSGustavo F. Padovan 
9920a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
9930a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
9940a708f8fSGustavo F. Padovan 
995ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
9960a708f8fSGustavo F. Padovan 
9970a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
9980a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
9990a708f8fSGustavo F. Padovan 	}
10000a708f8fSGustavo F. Padovan }
10010a708f8fSGustavo F. Padovan 
10020a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
10030a708f8fSGustavo F. Padovan {
10040a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
10050a708f8fSGustavo F. Padovan 	if (!disable_ertm)
10060a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
10070a708f8fSGustavo F. Padovan 
10080a708f8fSGustavo F. Padovan 	switch (mode) {
10090a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
10100a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
10110a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
10120a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
10130a708f8fSGustavo F. Padovan 	default:
10140a708f8fSGustavo F. Padovan 		return 0x00;
10150a708f8fSGustavo F. Padovan 	}
10160a708f8fSGustavo F. Padovan }
10170a708f8fSGustavo F. Padovan 
10184519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
10190a708f8fSGustavo F. Padovan {
10206be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
10210a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
10220a708f8fSGustavo F. Padovan 
10230a708f8fSGustavo F. Padovan 	if (!conn)
10240a708f8fSGustavo F. Padovan 		return;
10250a708f8fSGustavo F. Padovan 
10260c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
10271a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
10281a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
10291a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
10300a708f8fSGustavo F. Padovan 	}
10310a708f8fSGustavo F. Padovan 
1032416fa752SAndrei Emeltchenko 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1033416fa752SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_DISCONN);
1034416fa752SAndrei Emeltchenko 		return;
1035416fa752SAndrei Emeltchenko 	}
1036416fa752SAndrei Emeltchenko 
1037fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1038fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10390a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10400a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10410a708f8fSGustavo F. Padovan 
10426be36555SAndrei Emeltchenko 	lock_sock(sk);
10430e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10442e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10456be36555SAndrei Emeltchenko 	release_sock(sk);
10460a708f8fSGustavo F. Padovan }
10470a708f8fSGustavo F. Padovan 
10480a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10490a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10500a708f8fSGustavo F. Padovan {
10513df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10520a708f8fSGustavo F. Padovan 
10530a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10540a708f8fSGustavo F. Padovan 
10553df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10560a708f8fSGustavo F. Padovan 
10573df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
105848454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1059baa7e1faSGustavo F. Padovan 
10606be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10610a708f8fSGustavo F. Padovan 
1062715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10636be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10640a708f8fSGustavo F. Padovan 			continue;
10650a708f8fSGustavo F. Padovan 		}
10660a708f8fSGustavo F. Padovan 
106789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1068d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1069b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10706be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10710a708f8fSGustavo F. Padovan 				continue;
10720a708f8fSGustavo F. Padovan 			}
10730a708f8fSGustavo F. Padovan 
1074c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1075c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1076c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10770f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10786be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10790a708f8fSGustavo F. Padovan 				continue;
10800a708f8fSGustavo F. Padovan 			}
10810a708f8fSGustavo F. Padovan 
10829b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10830a708f8fSGustavo F. Padovan 
108489bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
10850a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
10860a708f8fSGustavo F. Padovan 			char buf[128];
1087fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1088fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
10890a708f8fSGustavo F. Padovan 
1090d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
10916be36555SAndrei Emeltchenko 				lock_sock(sk);
1092c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1093c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
10940a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
1095ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1096ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
109705e9a2f6SIlia Kolomisnky 					if (parent)
10980a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
10990a708f8fSGustavo F. Padovan 
11000a708f8fSGustavo F. Padovan 				} else {
11010e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
1102ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1103ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
11040a708f8fSGustavo F. Padovan 				}
11056be36555SAndrei Emeltchenko 				release_sock(sk);
11060a708f8fSGustavo F. Padovan 			} else {
1107ac73498cSAndrei Emeltchenko 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1108ac73498cSAndrei Emeltchenko 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
11090a708f8fSGustavo F. Padovan 			}
11100a708f8fSGustavo F. Padovan 
1111fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1112fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
11130a708f8fSGustavo F. Padovan 
1114c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
11150a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
11166be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
11170a708f8fSGustavo F. Padovan 				continue;
11180a708f8fSGustavo F. Padovan 			}
11190a708f8fSGustavo F. Padovan 
1120c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
11210a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
112273ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
112373ffa904SGustavo F. Padovan 			chan->num_conf_req++;
11240a708f8fSGustavo F. Padovan 		}
11250a708f8fSGustavo F. Padovan 
11266be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
11270a708f8fSGustavo F. Padovan 	}
11280a708f8fSGustavo F. Padovan 
11293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
11300a708f8fSGustavo F. Padovan }
11310a708f8fSGustavo F. Padovan 
1132c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1133b62f328bSVille Tervo  * Returns closest match, locked.
1134b62f328bSVille Tervo  */
1135d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1136c2287681SIdo Yariv 						    bdaddr_t *src,
1137c2287681SIdo Yariv 						    bdaddr_t *dst)
1138b62f328bSVille Tervo {
113923691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1140b62f328bSVille Tervo 
114123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1142b62f328bSVille Tervo 
114323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
114423691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1145fe4128e0SGustavo F. Padovan 
114689bc500eSGustavo F. Padovan 		if (state && c->state != state)
1147b62f328bSVille Tervo 			continue;
1148b62f328bSVille Tervo 
114923691d75SGustavo F. Padovan 		if (c->scid == cid) {
1150c2287681SIdo Yariv 			int src_match, dst_match;
1151c2287681SIdo Yariv 			int src_any, dst_any;
1152c2287681SIdo Yariv 
1153b62f328bSVille Tervo 			/* Exact match. */
1154c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1155c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1156c2287681SIdo Yariv 			if (src_match && dst_match) {
115723691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
115823691d75SGustavo F. Padovan 				return c;
115923691d75SGustavo F. Padovan 			}
1160b62f328bSVille Tervo 
1161b62f328bSVille Tervo 			/* Closest match */
1162c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1163c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1164c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1165c2287681SIdo Yariv 			    (src_any && dst_any))
116623691d75SGustavo F. Padovan 				c1 = c;
1167b62f328bSVille Tervo 		}
1168b62f328bSVille Tervo 	}
1169280f294fSGustavo F. Padovan 
117023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1171b62f328bSVille Tervo 
117223691d75SGustavo F. Padovan 	return c1;
1173b62f328bSVille Tervo }
1174b62f328bSVille Tervo 
1175b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1176b62f328bSVille Tervo {
1177c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
117823691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1179b62f328bSVille Tervo 
1180b62f328bSVille Tervo 	BT_DBG("");
1181b62f328bSVille Tervo 
1182b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
118323691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1184c2287681SIdo Yariv 					  conn->src, conn->dst);
118523691d75SGustavo F. Padovan 	if (!pchan)
1186b62f328bSVille Tervo 		return;
1187b62f328bSVille Tervo 
118823691d75SGustavo F. Padovan 	parent = pchan->sk;
118923691d75SGustavo F. Padovan 
1190aa2ac881SGustavo F. Padovan 	lock_sock(parent);
119162f3a2cfSGustavo F. Padovan 
119280b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
119380808e43SGustavo F. Padovan 	if (!chan)
1194b62f328bSVille Tervo 		goto clean;
1195b62f328bSVille Tervo 
119680808e43SGustavo F. Padovan 	sk = chan->sk;
11975d41ce1dSGustavo F. Padovan 
1198b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1199b62f328bSVille Tervo 
1200b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1201b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1202b62f328bSVille Tervo 
1203d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1204d1010240SGustavo F. Padovan 
12053d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
120648454079SGustavo F. Padovan 
12076754e0dfSGustavo Padovan 	l2cap_chan_ready(chan);
1208b62f328bSVille Tervo 
1209b62f328bSVille Tervo clean:
1210aa2ac881SGustavo F. Padovan 	release_sock(parent);
1211b62f328bSVille Tervo }
1212b62f328bSVille Tervo 
12130a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
12140a708f8fSGustavo F. Padovan {
121548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12160a708f8fSGustavo F. Padovan 
12170a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12180a708f8fSGustavo F. Padovan 
1219b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1220b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1221b62f328bSVille Tervo 
1222160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1223160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1224160dc6acSVinicius Costa Gomes 
12253df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12260a708f8fSGustavo F. Padovan 
12273df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1228baa7e1faSGustavo F. Padovan 
12296be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12300a708f8fSGustavo F. Padovan 
1231416fa752SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1232416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1233416fa752SAndrei Emeltchenko 			continue;
1234416fa752SAndrei Emeltchenko 		}
1235416fa752SAndrei Emeltchenko 
123663128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1237b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1238cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1239acd7d370SVille Tervo 
124063128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12416be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1242c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12436be36555SAndrei Emeltchenko 			lock_sock(sk);
12440e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12450a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12466be36555SAndrei Emeltchenko 			release_sock(sk);
1247b501d6a1SAnderson Briglia 
124889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1249fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12500a708f8fSGustavo F. Padovan 
12516be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12520a708f8fSGustavo F. Padovan 	}
12530a708f8fSGustavo F. Padovan 
12543df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12550a708f8fSGustavo F. Padovan }
12560a708f8fSGustavo F. Padovan 
12570a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12580a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12590a708f8fSGustavo F. Padovan {
126048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12610a708f8fSGustavo F. Padovan 
12620a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12630a708f8fSGustavo F. Padovan 
12643df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12650a708f8fSGustavo F. Padovan 
12663df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1267ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12682e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12690a708f8fSGustavo F. Padovan 	}
12700a708f8fSGustavo F. Padovan 
12713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12720a708f8fSGustavo F. Padovan }
12730a708f8fSGustavo F. Padovan 
1274f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12750a708f8fSGustavo F. Padovan {
1276f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1277030013d8SGustavo F. Padovan 							info_timer.work);
12780a708f8fSGustavo F. Padovan 
12790a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
12800a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
12810a708f8fSGustavo F. Padovan 
12820a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
12830a708f8fSGustavo F. Padovan }
12840a708f8fSGustavo F. Padovan 
12855d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
12865d3de7dfSVinicius Costa Gomes {
12875d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
12885d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
12895d3de7dfSVinicius Costa Gomes 
12905d3de7dfSVinicius Costa Gomes 	if (!conn)
12915d3de7dfSVinicius Costa Gomes 		return;
12925d3de7dfSVinicius Costa Gomes 
12935d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
12945d3de7dfSVinicius Costa Gomes 
12955d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
12965d3de7dfSVinicius Costa Gomes 
12973df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12983df91ea2SAndrei Emeltchenko 
12995d3de7dfSVinicius Costa Gomes 	/* Kill channels */
13005d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
130161d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
13026be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13036be36555SAndrei Emeltchenko 
13045d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
13056be36555SAndrei Emeltchenko 
13066be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13076be36555SAndrei Emeltchenko 
130880b98027SGustavo Padovan 		chan->ops->close(chan);
130961d6ef3eSMat Martineau 		l2cap_chan_put(chan);
13105d3de7dfSVinicius Costa Gomes 	}
13115d3de7dfSVinicius Costa Gomes 
13123df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
13133df91ea2SAndrei Emeltchenko 
131473d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
131573d80debSLuiz Augusto von Dentz 
13165d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1317127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
13185d3de7dfSVinicius Costa Gomes 
131951a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1320127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
13218aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1322d26a2345SVinicius Costa Gomes 	}
13235d3de7dfSVinicius Costa Gomes 
13245d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
13255d3de7dfSVinicius Costa Gomes 	kfree(conn);
13265d3de7dfSVinicius Costa Gomes }
13275d3de7dfSVinicius Costa Gomes 
13286c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
13295d3de7dfSVinicius Costa Gomes {
13306c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
13316c9d42a1SGustavo F. Padovan 						security_timer.work);
13325d3de7dfSVinicius Costa Gomes 
1333d06cc416SJohan Hedberg 	BT_DBG("conn %p", conn);
1334d06cc416SJohan Hedberg 
1335d06cc416SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1336d06cc416SJohan Hedberg 		smp_chan_destroy(conn);
13375d3de7dfSVinicius Costa Gomes 		l2cap_conn_del(conn->hcon, ETIMEDOUT);
13385d3de7dfSVinicius Costa Gomes 	}
1339d06cc416SJohan Hedberg }
13405d3de7dfSVinicius Costa Gomes 
13410a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13420a708f8fSGustavo F. Padovan {
13430a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
134473d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13450a708f8fSGustavo F. Padovan 
13460a708f8fSGustavo F. Padovan 	if (conn || status)
13470a708f8fSGustavo F. Padovan 		return conn;
13480a708f8fSGustavo F. Padovan 
134973d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
135073d80debSLuiz Augusto von Dentz 	if (!hchan)
13510a708f8fSGustavo F. Padovan 		return NULL;
13520a708f8fSGustavo F. Padovan 
135373d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
135473d80debSLuiz Augusto von Dentz 	if (!conn) {
135573d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
135673d80debSLuiz Augusto von Dentz 		return NULL;
135773d80debSLuiz Augusto von Dentz 	}
135873d80debSLuiz Augusto von Dentz 
13590a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13600a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
136173d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13620a708f8fSGustavo F. Padovan 
136373d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13640a708f8fSGustavo F. Padovan 
1365acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1366acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1367acd7d370SVille Tervo 	else
13680a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1369acd7d370SVille Tervo 
13700a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13710a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13720a708f8fSGustavo F. Padovan 
13730a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13740a708f8fSGustavo F. Padovan 
13750a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13763df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1377baa7e1faSGustavo F. Padovan 
1378baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13790a708f8fSGustavo F. Padovan 
13805d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13816c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13825d3de7dfSVinicius Costa Gomes 	else
1383030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
13840a708f8fSGustavo F. Padovan 
13859f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
13860a708f8fSGustavo F. Padovan 
13870a708f8fSGustavo F. Padovan 	return conn;
13880a708f8fSGustavo F. Padovan }
13890a708f8fSGustavo F. Padovan 
13900a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
13910a708f8fSGustavo F. Padovan 
1392c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
13930a708f8fSGustavo F. Padovan  * Returns closest match.
13940a708f8fSGustavo F. Padovan  */
1395c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1396c2287681SIdo Yariv 						   bdaddr_t *src,
1397c2287681SIdo Yariv 						   bdaddr_t *dst)
13980a708f8fSGustavo F. Padovan {
139923691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
14000a708f8fSGustavo F. Padovan 
140123691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
14020a708f8fSGustavo F. Padovan 
140323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
140423691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1405fe4128e0SGustavo F. Padovan 
140689bc500eSGustavo F. Padovan 		if (state && c->state != state)
14070a708f8fSGustavo F. Padovan 			continue;
14080a708f8fSGustavo F. Padovan 
140923691d75SGustavo F. Padovan 		if (c->psm == psm) {
1410c2287681SIdo Yariv 			int src_match, dst_match;
1411c2287681SIdo Yariv 			int src_any, dst_any;
1412c2287681SIdo Yariv 
14130a708f8fSGustavo F. Padovan 			/* Exact match. */
1414c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1415c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1416c2287681SIdo Yariv 			if (src_match && dst_match) {
1417a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
141823691d75SGustavo F. Padovan 				return c;
141923691d75SGustavo F. Padovan 			}
14200a708f8fSGustavo F. Padovan 
14210a708f8fSGustavo F. Padovan 			/* Closest match */
1422c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1423c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1424c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1425c2287681SIdo Yariv 			    (src_any && dst_any))
142623691d75SGustavo F. Padovan 				c1 = c;
14270a708f8fSGustavo F. Padovan 		}
14280a708f8fSGustavo F. Padovan 	}
14290a708f8fSGustavo F. Padovan 
143023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
14310a708f8fSGustavo F. Padovan 
143223691d75SGustavo F. Padovan 	return c1;
14330a708f8fSGustavo F. Padovan }
14340a708f8fSGustavo F. Padovan 
14358e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
14368e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14370a708f8fSGustavo F. Padovan {
14385d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14390a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14400a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14410a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14420a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14430a708f8fSGustavo F. Padovan 	__u8 auth_type;
14440a708f8fSGustavo F. Padovan 	int err;
14450a708f8fSGustavo F. Padovan 
14468e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14478e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14480a708f8fSGustavo F. Padovan 
14490a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14500a708f8fSGustavo F. Padovan 	if (!hdev)
14510a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14520a708f8fSGustavo F. Padovan 
145309fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14540a708f8fSGustavo F. Padovan 
14556be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
145603a00194SGustavo F. Padovan 
145703a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
145803a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
145903a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
146003a00194SGustavo F. Padovan 		err = -EINVAL;
146103a00194SGustavo F. Padovan 		goto done;
146203a00194SGustavo F. Padovan 	}
146303a00194SGustavo F. Padovan 
146403a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
146503a00194SGustavo F. Padovan 		err = -EINVAL;
146603a00194SGustavo F. Padovan 		goto done;
146703a00194SGustavo F. Padovan 	}
146803a00194SGustavo F. Padovan 
146903a00194SGustavo F. Padovan 	switch (chan->mode) {
147003a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
147103a00194SGustavo F. Padovan 		break;
147203a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
147303a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
147403a00194SGustavo F. Padovan 		if (!disable_ertm)
147503a00194SGustavo F. Padovan 			break;
147603a00194SGustavo F. Padovan 		/* fall through */
147703a00194SGustavo F. Padovan 	default:
147803a00194SGustavo F. Padovan 		err = -ENOTSUPP;
147903a00194SGustavo F. Padovan 		goto done;
148003a00194SGustavo F. Padovan 	}
148103a00194SGustavo F. Padovan 
14820797e01dSGustavo Padovan 	switch (chan->state) {
148303a00194SGustavo F. Padovan 	case BT_CONNECT:
148403a00194SGustavo F. Padovan 	case BT_CONNECT2:
148503a00194SGustavo F. Padovan 	case BT_CONFIG:
148603a00194SGustavo F. Padovan 		/* Already connecting */
148703a00194SGustavo F. Padovan 		err = 0;
148803a00194SGustavo F. Padovan 		goto done;
148903a00194SGustavo F. Padovan 
149003a00194SGustavo F. Padovan 	case BT_CONNECTED:
149103a00194SGustavo F. Padovan 		/* Already connected */
149203a00194SGustavo F. Padovan 		err = -EISCONN;
149303a00194SGustavo F. Padovan 		goto done;
149403a00194SGustavo F. Padovan 
149503a00194SGustavo F. Padovan 	case BT_OPEN:
149603a00194SGustavo F. Padovan 	case BT_BOUND:
149703a00194SGustavo F. Padovan 		/* Can connect */
149803a00194SGustavo F. Padovan 		break;
149903a00194SGustavo F. Padovan 
150003a00194SGustavo F. Padovan 	default:
150103a00194SGustavo F. Padovan 		err = -EBADFD;
150203a00194SGustavo F. Padovan 		goto done;
150303a00194SGustavo F. Padovan 	}
150403a00194SGustavo F. Padovan 
150503a00194SGustavo F. Padovan 	/* Set destination address and psm */
15060797e01dSGustavo Padovan 	lock_sock(sk);
15079219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
15086be36555SAndrei Emeltchenko 	release_sock(sk);
15096be36555SAndrei Emeltchenko 
151003a00194SGustavo F. Padovan 	chan->psm = psm;
151103a00194SGustavo F. Padovan 	chan->dcid = cid;
15120a708f8fSGustavo F. Padovan 
15134343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
15140a708f8fSGustavo F. Padovan 
1515fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
15168e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
15174343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1518acd7d370SVille Tervo 	else
15198e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
15204343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1521acd7d370SVille Tervo 
152230e76272SVille Tervo 	if (IS_ERR(hcon)) {
152330e76272SVille Tervo 		err = PTR_ERR(hcon);
15240a708f8fSGustavo F. Padovan 		goto done;
152530e76272SVille Tervo 	}
15260a708f8fSGustavo F. Padovan 
15270a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
15280a708f8fSGustavo F. Padovan 	if (!conn) {
15290a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
153030e76272SVille Tervo 		err = -ENOMEM;
15310a708f8fSGustavo F. Padovan 		goto done;
15320a708f8fSGustavo F. Padovan 	}
15330a708f8fSGustavo F. Padovan 
15349f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15359f0caeb1SVinicius Costa Gomes 		err = 0;
15369f0caeb1SVinicius Costa Gomes 
15379f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15389f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15399f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15409f0caeb1SVinicius Costa Gomes 		}
15419f0caeb1SVinicius Costa Gomes 
15429f0caeb1SVinicius Costa Gomes 		if (err)
15439f0caeb1SVinicius Costa Gomes 			goto done;
15449f0caeb1SVinicius Costa Gomes 	}
15459f0caeb1SVinicius Costa Gomes 
15460a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15470a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15480a708f8fSGustavo F. Padovan 
15496be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
155048454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15516be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
155248454079SGustavo F. Padovan 
15536be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1554c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15550a708f8fSGustavo F. Padovan 
15560a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1557715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1558c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1559d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15606be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15610a708f8fSGustavo F. Padovan 		} else
1562fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15630a708f8fSGustavo F. Padovan 	}
15640a708f8fSGustavo F. Padovan 
156530e76272SVille Tervo 	err = 0;
156630e76272SVille Tervo 
15670a708f8fSGustavo F. Padovan done:
15686be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
156909fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15700a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15710a708f8fSGustavo F. Padovan 	return err;
15720a708f8fSGustavo F. Padovan }
15730a708f8fSGustavo F. Padovan 
1574dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15750a708f8fSGustavo F. Padovan {
15768c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15770a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
15780a708f8fSGustavo F. Padovan 	int err = 0;
15790a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
15800a708f8fSGustavo F. Padovan 
15810a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
15820a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1583a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
15840a708f8fSGustavo F. Padovan 		if (!timeo)
15850a708f8fSGustavo F. Padovan 			timeo = HZ/5;
15860a708f8fSGustavo F. Padovan 
15870a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
15880a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
15890a708f8fSGustavo F. Padovan 			break;
15900a708f8fSGustavo F. Padovan 		}
15910a708f8fSGustavo F. Padovan 
15920a708f8fSGustavo F. Padovan 		release_sock(sk);
15930a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
15940a708f8fSGustavo F. Padovan 		lock_sock(sk);
1595a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
15960a708f8fSGustavo F. Padovan 
15970a708f8fSGustavo F. Padovan 		err = sock_error(sk);
15980a708f8fSGustavo F. Padovan 		if (err)
15990a708f8fSGustavo F. Padovan 			break;
16000a708f8fSGustavo F. Padovan 	}
16010a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
16020a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
16030a708f8fSGustavo F. Padovan 	return err;
16040a708f8fSGustavo F. Padovan }
16050a708f8fSGustavo F. Padovan 
1606721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
16070a708f8fSGustavo F. Padovan {
1608721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1609721c4181SGustavo F. Padovan 					       monitor_timer.work);
16100a708f8fSGustavo F. Padovan 
1611525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
16120a708f8fSGustavo F. Padovan 
16136be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16146be36555SAndrei Emeltchenko 
161580909e04SMat Martineau 	if (!chan->conn) {
16166be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16178d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
16180a708f8fSGustavo F. Padovan 		return;
16190a708f8fSGustavo F. Padovan 	}
16200a708f8fSGustavo F. Padovan 
1621401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
16220a708f8fSGustavo F. Padovan 
16236be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16248d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16250a708f8fSGustavo F. Padovan }
16260a708f8fSGustavo F. Padovan 
1627721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
16280a708f8fSGustavo F. Padovan {
1629721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1630721c4181SGustavo F. Padovan 					       retrans_timer.work);
16310a708f8fSGustavo F. Padovan 
163249208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16330a708f8fSGustavo F. Padovan 
16346be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16356be36555SAndrei Emeltchenko 
163680909e04SMat Martineau 	if (!chan->conn) {
163780909e04SMat Martineau 		l2cap_chan_unlock(chan);
163880909e04SMat Martineau 		l2cap_chan_put(chan);
163980909e04SMat Martineau 		return;
164080909e04SMat Martineau 	}
16410a708f8fSGustavo F. Padovan 
1642401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
16436be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16448d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16450a708f8fSGustavo F. Padovan }
16460a708f8fSGustavo F. Padovan 
1647d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
16483733937dSMat Martineau 				 struct sk_buff_head *skbs)
16490a708f8fSGustavo F. Padovan {
16500a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16513733937dSMat Martineau 	struct l2cap_ctrl *control;
16520a708f8fSGustavo F. Padovan 
16533733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
16543733937dSMat Martineau 
16553733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
16563733937dSMat Martineau 
16573733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
16583733937dSMat Martineau 
16593733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
16603733937dSMat Martineau 
16613733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
16623733937dSMat Martineau 		control = &bt_cb(skb)->control;
16633733937dSMat Martineau 
16643733937dSMat Martineau 		control->reqseq = 0;
16653733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
16663733937dSMat Martineau 
16673733937dSMat Martineau 		__pack_control(chan, control, skb);
16680a708f8fSGustavo F. Padovan 
166947d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
16703733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
16713733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
16720a708f8fSGustavo F. Padovan 		}
16730a708f8fSGustavo F. Padovan 
16744343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16750a708f8fSGustavo F. Padovan 
1676b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
16773733937dSMat Martineau 
1678836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
16793733937dSMat Martineau 		chan->frames_sent++;
16800a708f8fSGustavo F. Padovan 	}
16810a708f8fSGustavo F. Padovan }
16820a708f8fSGustavo F. Padovan 
168367c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
16840a708f8fSGustavo F. Padovan {
16850a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
168618a48e76SMat Martineau 	struct l2cap_ctrl *control;
168718a48e76SMat Martineau 	int sent = 0;
168818a48e76SMat Martineau 
168918a48e76SMat Martineau 	BT_DBG("chan %p", chan);
16900a708f8fSGustavo F. Padovan 
169189bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
16920a708f8fSGustavo F. Padovan 		return -ENOTCONN;
16930a708f8fSGustavo F. Padovan 
169494122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
169594122bbeSMat Martineau 		return 0;
169694122bbeSMat Martineau 
169718a48e76SMat Martineau 	while (chan->tx_send_head &&
169818a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
169918a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
17000a708f8fSGustavo F. Padovan 
170118a48e76SMat Martineau 		skb = chan->tx_send_head;
17020a708f8fSGustavo F. Padovan 
170318a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
170418a48e76SMat Martineau 		control = &bt_cb(skb)->control;
17050a708f8fSGustavo F. Padovan 
1706e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
170718a48e76SMat Martineau 			control->final = 1;
1708e2ab4353SGustavo F. Padovan 
170918a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
171018a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
171118a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
17120a708f8fSGustavo F. Padovan 
171318a48e76SMat Martineau 		__pack_control(chan, control, skb);
17140a708f8fSGustavo F. Padovan 
171547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
171618a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
171718a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
17180a708f8fSGustavo F. Padovan 		}
17190a708f8fSGustavo F. Padovan 
172018a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
172118a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
172218a48e76SMat Martineau 		 */
172318a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
172418a48e76SMat Martineau 
172518a48e76SMat Martineau 		if (!tx_skb)
172618a48e76SMat Martineau 			break;
17270a708f8fSGustavo F. Padovan 
17281a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17290a708f8fSGustavo F. Padovan 
1730836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17316a026610SGustavo F. Padovan 		chan->unacked_frames++;
17326a026610SGustavo F. Padovan 		chan->frames_sent++;
173318a48e76SMat Martineau 		sent++;
17340a708f8fSGustavo F. Padovan 
173558d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
173658d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17370a708f8fSGustavo F. Padovan 		else
173858d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
173918a48e76SMat Martineau 
174018a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
1741b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
17420a708f8fSGustavo F. Padovan 	}
17430a708f8fSGustavo F. Padovan 
1744b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
1745b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
174618a48e76SMat Martineau 
174718a48e76SMat Martineau 	return sent;
17480a708f8fSGustavo F. Padovan }
17490a708f8fSGustavo F. Padovan 
1750e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1751e1fbd4c1SMat Martineau {
1752e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1753e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1754e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1755e1fbd4c1SMat Martineau 	u16 seq;
1756e1fbd4c1SMat Martineau 
1757e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1758e1fbd4c1SMat Martineau 
1759e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1760e1fbd4c1SMat Martineau 		return;
1761e1fbd4c1SMat Martineau 
1762e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1763e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1764e1fbd4c1SMat Martineau 
1765e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1766e1fbd4c1SMat Martineau 		if (!skb) {
1767e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
1768e1fbd4c1SMat Martineau 				seq);
1769e1fbd4c1SMat Martineau 			continue;
1770e1fbd4c1SMat Martineau 		}
1771e1fbd4c1SMat Martineau 
1772e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
1773e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
1774e1fbd4c1SMat Martineau 
1775e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
1776e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
1777e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
1778e1fbd4c1SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
1779e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1780e1fbd4c1SMat Martineau 			break;
1781e1fbd4c1SMat Martineau 		}
1782e1fbd4c1SMat Martineau 
1783e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
1784e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
1785e1fbd4c1SMat Martineau 			control.final = 1;
1786e1fbd4c1SMat Martineau 		else
1787e1fbd4c1SMat Martineau 			control.final = 0;
1788e1fbd4c1SMat Martineau 
1789e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
1790e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
1791e1fbd4c1SMat Martineau 			 * writeable copy
1792e1fbd4c1SMat Martineau 			 */
1793e1fbd4c1SMat Martineau 			tx_skb = skb_copy(skb, GFP_ATOMIC);
1794e1fbd4c1SMat Martineau 		} else {
1795e1fbd4c1SMat Martineau 			tx_skb = skb_clone(skb, GFP_ATOMIC);
1796e1fbd4c1SMat Martineau 		}
1797e1fbd4c1SMat Martineau 
1798e1fbd4c1SMat Martineau 		if (!tx_skb) {
1799e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1800e1fbd4c1SMat Martineau 			break;
1801e1fbd4c1SMat Martineau 		}
1802e1fbd4c1SMat Martineau 
1803e1fbd4c1SMat Martineau 		/* Update skb contents */
1804e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1805e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
1806e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1807e1fbd4c1SMat Martineau 		} else {
1808e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
1809e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1810e1fbd4c1SMat Martineau 		}
1811e1fbd4c1SMat Martineau 
1812e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
1813e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
1814e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
1815e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
1816e1fbd4c1SMat Martineau 		}
1817e1fbd4c1SMat Martineau 
1818e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
1819e1fbd4c1SMat Martineau 
1820e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
1821e1fbd4c1SMat Martineau 
1822e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
1823e1fbd4c1SMat Martineau 	}
1824e1fbd4c1SMat Martineau }
1825e1fbd4c1SMat Martineau 
1826f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
1827f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
1828f80842a8SMat Martineau {
1829f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1830f80842a8SMat Martineau 
1831f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
1832f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
1833f80842a8SMat Martineau }
1834f80842a8SMat Martineau 
1835d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
1836d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
1837d2a7ac5dSMat Martineau {
1838e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1839e1fbd4c1SMat Martineau 
1840e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1841e1fbd4c1SMat Martineau 
1842e1fbd4c1SMat Martineau 	if (control->poll)
1843e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
1844e1fbd4c1SMat Martineau 
1845e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
1846e1fbd4c1SMat Martineau 
1847e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1848e1fbd4c1SMat Martineau 		return;
1849e1fbd4c1SMat Martineau 
1850e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
1851e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
1852e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
1853e1fbd4c1SMat Martineau 				skb == chan->tx_send_head)
1854e1fbd4c1SMat Martineau 				break;
1855e1fbd4c1SMat Martineau 		}
1856e1fbd4c1SMat Martineau 
1857e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
1858e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
1859e1fbd4c1SMat Martineau 				break;
1860e1fbd4c1SMat Martineau 
1861e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
1862e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
1863e1fbd4c1SMat Martineau 		}
1864e1fbd4c1SMat Martineau 
1865e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
1866e1fbd4c1SMat Martineau 	}
1867d2a7ac5dSMat Martineau }
1868d2a7ac5dSMat Martineau 
1869b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1870b17e73bbSSzymon Janc {
18710a0aba42SMat Martineau 	struct l2cap_ctrl control;
18720a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
18730a0aba42SMat Martineau 					 chan->last_acked_seq);
18740a0aba42SMat Martineau 	int threshold;
18750a0aba42SMat Martineau 
18760a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
18770a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
18780a0aba42SMat Martineau 
18790a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
18800a0aba42SMat Martineau 	control.sframe = 1;
18810a0aba42SMat Martineau 
18820a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
18830a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
1884b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
18850a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
18860a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
18870a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
18880a0aba42SMat Martineau 	} else {
18890a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
18900a0aba42SMat Martineau 			l2cap_ertm_send(chan);
18910a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
18920a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
18930a0aba42SMat Martineau 				frames_to_ack = 0;
18940a0aba42SMat Martineau 		}
18950a0aba42SMat Martineau 
1896c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
18970a0aba42SMat Martineau 		 * Calculate without mul or div
18980a0aba42SMat Martineau 		 */
1899c20f8e35SMat Martineau 		threshold = chan->ack_win;
19000a0aba42SMat Martineau 		threshold += threshold << 1;
19010a0aba42SMat Martineau 		threshold >>= 2;
19020a0aba42SMat Martineau 
1903b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
19040a0aba42SMat Martineau 		       threshold);
19050a0aba42SMat Martineau 
19060a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
19070a0aba42SMat Martineau 			__clear_ack_timer(chan);
19080a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
19090a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
19100a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
19110a0aba42SMat Martineau 			frames_to_ack = 0;
19120a0aba42SMat Martineau 		}
19130a0aba42SMat Martineau 
19140a0aba42SMat Martineau 		if (frames_to_ack)
19150a0aba42SMat Martineau 			__set_ack_timer(chan);
19160a0aba42SMat Martineau 	}
1917b17e73bbSSzymon Janc }
1918b17e73bbSSzymon Janc 
191904124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
192004124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
192104124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
19220a708f8fSGustavo F. Padovan {
19230952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
19240a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
192590338947SGustavo Padovan 	int sent = 0;
19260a708f8fSGustavo F. Padovan 
19270a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
19280a708f8fSGustavo F. Padovan 		return -EFAULT;
19290a708f8fSGustavo F. Padovan 
19300a708f8fSGustavo F. Padovan 	sent += count;
19310a708f8fSGustavo F. Padovan 	len  -= count;
19320a708f8fSGustavo F. Padovan 
19330a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
19340a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
19350a708f8fSGustavo F. Padovan 	while (len) {
1936fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1937fbe00700SGustavo Padovan 
19380a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
19390a708f8fSGustavo F. Padovan 
1940fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
194190338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1942fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1943fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
19442f7719ceSAndrei Emeltchenko 
1945fbe00700SGustavo Padovan 		*frag = tmp;
1946fbe00700SGustavo Padovan 
19470a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
19480a708f8fSGustavo F. Padovan 			return -EFAULT;
19490a708f8fSGustavo F. Padovan 
19505e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
19515e59b791SLuiz Augusto von Dentz 
19520a708f8fSGustavo F. Padovan 		sent += count;
19530a708f8fSGustavo F. Padovan 		len  -= count;
19540a708f8fSGustavo F. Padovan 
19552d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
19562d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
19572d0ed3d5SGustavo Padovan 
19580a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
19590a708f8fSGustavo F. Padovan 	}
19600a708f8fSGustavo F. Padovan 
19610a708f8fSGustavo F. Padovan 	return sent;
19620a708f8fSGustavo F. Padovan }
19630a708f8fSGustavo F. Padovan 
19645e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
19655e59b791SLuiz Augusto von Dentz 						 struct msghdr *msg, size_t len,
19665e59b791SLuiz Augusto von Dentz 						 u32 priority)
19670a708f8fSGustavo F. Padovan {
19688c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19690a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
197003a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
19710a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19720a708f8fSGustavo F. Padovan 
1973b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu priority %u", chan, len, priority);
19740a708f8fSGustavo F. Padovan 
19750a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19762f7719ceSAndrei Emeltchenko 
19772f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
197890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
197990338947SGustavo Padovan 	if (IS_ERR(skb))
198090338947SGustavo Padovan 		return skb;
19810a708f8fSGustavo F. Padovan 
19825e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
19835e59b791SLuiz Augusto von Dentz 
19840a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
19850a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
1986fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
1987daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
1988daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
19890a708f8fSGustavo F. Padovan 
19900952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
19910a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
19920a708f8fSGustavo F. Padovan 		kfree_skb(skb);
19930a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
19940a708f8fSGustavo F. Padovan 	}
19950a708f8fSGustavo F. Padovan 	return skb;
19960a708f8fSGustavo F. Padovan }
19970a708f8fSGustavo F. Padovan 
19985e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
19995e59b791SLuiz Augusto von Dentz 					      struct msghdr *msg, size_t len,
20005e59b791SLuiz Augusto von Dentz 					      u32 priority)
20010a708f8fSGustavo F. Padovan {
20028c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20030a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2004f2ba7faeSGustavo Padovan 	int err, count;
20050a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20060a708f8fSGustavo F. Padovan 
2007b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
20080a708f8fSGustavo F. Padovan 
2009f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
20102f7719ceSAndrei Emeltchenko 
2011f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
201290338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
201390338947SGustavo Padovan 	if (IS_ERR(skb))
201490338947SGustavo Padovan 		return skb;
20150a708f8fSGustavo F. Padovan 
20165e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20175e59b791SLuiz Augusto von Dentz 
20180a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20190a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2020fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20216ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
20220a708f8fSGustavo F. Padovan 
20230952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20240a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20250a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20260a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20270a708f8fSGustavo F. Padovan 	}
20280a708f8fSGustavo F. Padovan 	return skb;
20290a708f8fSGustavo F. Padovan }
20300a708f8fSGustavo F. Padovan 
2031ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2032ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
203394122bbeSMat Martineau 					       u16 sdulen)
20340a708f8fSGustavo F. Padovan {
20358c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20360a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2037e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
20380a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20390a708f8fSGustavo F. Padovan 
2040b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
20410a708f8fSGustavo F. Padovan 
20420a708f8fSGustavo F. Padovan 	if (!conn)
20430a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
20440a708f8fSGustavo F. Padovan 
2045ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2046e4ca6d98SAndrei Emeltchenko 
20470a708f8fSGustavo F. Padovan 	if (sdulen)
204803a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
20490a708f8fSGustavo F. Padovan 
205047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
205103a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
20520a708f8fSGustavo F. Padovan 
20530a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
20542f7719ceSAndrei Emeltchenko 
20552f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
205690338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
205790338947SGustavo Padovan 	if (IS_ERR(skb))
205890338947SGustavo Padovan 		return skb;
20590a708f8fSGustavo F. Padovan 
20600a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20610a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2062fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20630a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
206488843ab0SAndrei Emeltchenko 
206518a48e76SMat Martineau 	/* Control header is populated later */
206618a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
206718a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
206818a48e76SMat Martineau 	else
206918a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
207088843ab0SAndrei Emeltchenko 
20710a708f8fSGustavo F. Padovan 	if (sdulen)
207203a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
20730a708f8fSGustavo F. Padovan 
20740952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20750a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20760a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20770a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20780a708f8fSGustavo F. Padovan 	}
20790a708f8fSGustavo F. Padovan 
208018a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
20813ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
20820a708f8fSGustavo F. Padovan 	return skb;
20830a708f8fSGustavo F. Padovan }
20840a708f8fSGustavo F. Padovan 
208594122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
208694122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
208794122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
20880a708f8fSGustavo F. Padovan {
20890a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
209094122bbeSMat Martineau 	u16 sdu_len;
209194122bbeSMat Martineau 	size_t pdu_len;
209294122bbeSMat Martineau 	u8 sar;
20930a708f8fSGustavo F. Padovan 
2094b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
20950a708f8fSGustavo F. Padovan 
209694122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
209794122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
209894122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
209994122bbeSMat Martineau 	 */
210094122bbeSMat Martineau 
210194122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
210294122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
210394122bbeSMat Martineau 
210494122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
210594122bbeSMat Martineau 
210694122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
210735d401dfSGustavo Padovan 	if (chan->fcs)
210835d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
210935d401dfSGustavo Padovan 
2110ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
211194122bbeSMat Martineau 
211294122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
211394122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
211494122bbeSMat Martineau 
211594122bbeSMat Martineau 	if (len <= pdu_len) {
211694122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
211794122bbeSMat Martineau 		sdu_len = 0;
211894122bbeSMat Martineau 		pdu_len = len;
211994122bbeSMat Martineau 	} else {
212094122bbeSMat Martineau 		sar = L2CAP_SAR_START;
212194122bbeSMat Martineau 		sdu_len = len;
212294122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
212394122bbeSMat Martineau 	}
21240a708f8fSGustavo F. Padovan 
21250a708f8fSGustavo F. Padovan 	while (len > 0) {
212694122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
21270a708f8fSGustavo F. Padovan 
21280a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
212994122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
21300a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
21310a708f8fSGustavo F. Padovan 		}
21320a708f8fSGustavo F. Padovan 
213394122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
213494122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
21350a708f8fSGustavo F. Padovan 
213694122bbeSMat Martineau 		len -= pdu_len;
213794122bbeSMat Martineau 		if (sdu_len) {
213894122bbeSMat Martineau 			sdu_len = 0;
213994122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
214094122bbeSMat Martineau 		}
214194122bbeSMat Martineau 
214294122bbeSMat Martineau 		if (len <= pdu_len) {
214394122bbeSMat Martineau 			sar = L2CAP_SAR_END;
214494122bbeSMat Martineau 			pdu_len = len;
214594122bbeSMat Martineau 		} else {
214694122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
214794122bbeSMat Martineau 		}
214894122bbeSMat Martineau 	}
214994122bbeSMat Martineau 
2150f0f62799SGustavo Padovan 	return 0;
21510a708f8fSGustavo F. Padovan }
21520a708f8fSGustavo F. Padovan 
21535e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
21545e59b791SLuiz Augusto von Dentz 								u32 priority)
21559a91a04aSGustavo F. Padovan {
21569a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
21579a91a04aSGustavo F. Padovan 	int err;
215894122bbeSMat Martineau 	struct sk_buff_head seg_queue;
21599a91a04aSGustavo F. Padovan 
21609a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2161715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
21625e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
21639a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21649a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21659a91a04aSGustavo F. Padovan 
21669a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21679a91a04aSGustavo F. Padovan 		return len;
21689a91a04aSGustavo F. Padovan 	}
21699a91a04aSGustavo F. Padovan 
21709a91a04aSGustavo F. Padovan 	switch (chan->mode) {
21719a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
21729a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
21739a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
21749a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
21759a91a04aSGustavo F. Padovan 
21769a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
21775e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
21789a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21799a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21809a91a04aSGustavo F. Padovan 
21819a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21829a91a04aSGustavo F. Padovan 		err = len;
21839a91a04aSGustavo F. Padovan 		break;
21849a91a04aSGustavo F. Padovan 
21859a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
21869a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
218794122bbeSMat Martineau 		/* Check outgoing MTU */
218894122bbeSMat Martineau 		if (len > chan->omtu) {
218994122bbeSMat Martineau 			err = -EMSGSIZE;
21909a91a04aSGustavo F. Padovan 			break;
21919a91a04aSGustavo F. Padovan 		}
21929a91a04aSGustavo F. Padovan 
219394122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
219494122bbeSMat Martineau 
219594122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
219694122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
219794122bbeSMat Martineau 		 * allocation.
219894122bbeSMat Martineau 		 */
219994122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
220094122bbeSMat Martineau 
220194122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
220294122bbeSMat Martineau 		 * check that it is still connected.
220394122bbeSMat Martineau 		 */
220494122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
220594122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
220694122bbeSMat Martineau 			err = -ENOTCONN;
22079a91a04aSGustavo F. Padovan 		}
22089a91a04aSGustavo F. Padovan 
220994122bbeSMat Martineau 		if (err)
221094122bbeSMat Martineau 			break;
221194122bbeSMat Martineau 
22123733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2213d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
22143733937dSMat Martineau 		else
2215d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
221694122bbeSMat Martineau 
22179a91a04aSGustavo F. Padovan 		err = len;
22189a91a04aSGustavo F. Padovan 
221994122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
222094122bbeSMat Martineau 		 * seg_queue and need to be purged.
222194122bbeSMat Martineau 		 */
222294122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
22239a91a04aSGustavo F. Padovan 		break;
22249a91a04aSGustavo F. Padovan 
22259a91a04aSGustavo F. Padovan 	default:
22269a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
22279a91a04aSGustavo F. Padovan 		err = -EBADFD;
22289a91a04aSGustavo F. Padovan 	}
22299a91a04aSGustavo F. Padovan 
22309a91a04aSGustavo F. Padovan 	return err;
22319a91a04aSGustavo F. Padovan }
22329a91a04aSGustavo F. Padovan 
2233d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2234d2a7ac5dSMat Martineau {
2235bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2236bed68bdeSMat Martineau 	u16 seq;
2237bed68bdeSMat Martineau 
2238b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2239bed68bdeSMat Martineau 
2240bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2241bed68bdeSMat Martineau 	control.sframe = 1;
2242bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2243bed68bdeSMat Martineau 
2244bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2245bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2246bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2247bed68bdeSMat Martineau 			control.reqseq = seq;
2248bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2249bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2250bed68bdeSMat Martineau 		}
2251bed68bdeSMat Martineau 	}
2252bed68bdeSMat Martineau 
2253bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2254d2a7ac5dSMat Martineau }
2255d2a7ac5dSMat Martineau 
2256d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2257d2a7ac5dSMat Martineau {
2258bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2259bed68bdeSMat Martineau 
2260bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2261bed68bdeSMat Martineau 
2262bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2263bed68bdeSMat Martineau 		return;
2264bed68bdeSMat Martineau 
2265bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2266bed68bdeSMat Martineau 	control.sframe = 1;
2267bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2268bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2269bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2270d2a7ac5dSMat Martineau }
2271d2a7ac5dSMat Martineau 
2272d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2273d2a7ac5dSMat Martineau {
2274bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2275bed68bdeSMat Martineau 	u16 initial_head;
2276bed68bdeSMat Martineau 	u16 seq;
2277bed68bdeSMat Martineau 
2278b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2279bed68bdeSMat Martineau 
2280bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2281bed68bdeSMat Martineau 	control.sframe = 1;
2282bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2283bed68bdeSMat Martineau 
2284bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2285bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2286bed68bdeSMat Martineau 
2287bed68bdeSMat Martineau 	do {
2288bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2289bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2290bed68bdeSMat Martineau 			break;
2291bed68bdeSMat Martineau 
2292bed68bdeSMat Martineau 		control.reqseq = seq;
2293bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2294bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2295bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2296d2a7ac5dSMat Martineau }
2297d2a7ac5dSMat Martineau 
2298608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2299608bcc6dSMat Martineau {
2300608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2301608bcc6dSMat Martineau 	u16 ackseq;
2302608bcc6dSMat Martineau 
2303b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2304608bcc6dSMat Martineau 
2305608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2306608bcc6dSMat Martineau 		return;
2307608bcc6dSMat Martineau 
2308b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2309608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2310608bcc6dSMat Martineau 
2311608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2312608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2313608bcc6dSMat Martineau 
2314608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2315608bcc6dSMat Martineau 		if (acked_skb) {
2316608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2317608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2318608bcc6dSMat Martineau 			chan->unacked_frames--;
2319608bcc6dSMat Martineau 		}
2320608bcc6dSMat Martineau 	}
2321608bcc6dSMat Martineau 
2322608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2323608bcc6dSMat Martineau 
2324608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2325608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2326608bcc6dSMat Martineau 
2327b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2328608bcc6dSMat Martineau }
2329608bcc6dSMat Martineau 
2330608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2331608bcc6dSMat Martineau {
2332608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2333608bcc6dSMat Martineau 
2334608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2335608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2336608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2337608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2338608bcc6dSMat Martineau }
2339608bcc6dSMat Martineau 
2340d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2341608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2342608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2343608bcc6dSMat Martineau {
2344608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2345608bcc6dSMat Martineau 	       event);
2346608bcc6dSMat Martineau 
2347608bcc6dSMat Martineau 	switch (event) {
2348608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2349608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2350608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2351608bcc6dSMat Martineau 
2352608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2353608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2354608bcc6dSMat Martineau 		break;
2355608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2356608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2357608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2358608bcc6dSMat Martineau 
2359608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2360608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2361608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2362608bcc6dSMat Martineau 			 */
2363608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2364608bcc6dSMat Martineau 		}
2365608bcc6dSMat Martineau 
2366608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2367608bcc6dSMat Martineau 
2368608bcc6dSMat Martineau 		break;
2369608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2370608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2371608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2372608bcc6dSMat Martineau 
2373608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2374608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2375608bcc6dSMat Martineau 
2376608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2377608bcc6dSMat Martineau 			local_control.sframe = 1;
2378608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2379608bcc6dSMat Martineau 			local_control.poll = 1;
2380608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2381a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2382608bcc6dSMat Martineau 
2383608bcc6dSMat Martineau 			chan->retry_count = 1;
2384608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2385608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2386608bcc6dSMat Martineau 		}
2387608bcc6dSMat Martineau 		break;
2388608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2389608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2390608bcc6dSMat Martineau 		break;
2391608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2392608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2393608bcc6dSMat Martineau 		chan->retry_count = 1;
2394608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2395608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2396608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2397608bcc6dSMat Martineau 		break;
2398608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2399608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2400608bcc6dSMat Martineau 		chan->retry_count = 1;
2401608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2402608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2403608bcc6dSMat Martineau 		break;
2404608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2405608bcc6dSMat Martineau 		/* Nothing to process */
2406608bcc6dSMat Martineau 		break;
2407608bcc6dSMat Martineau 	default:
2408608bcc6dSMat Martineau 		break;
2409608bcc6dSMat Martineau 	}
2410608bcc6dSMat Martineau }
2411608bcc6dSMat Martineau 
2412d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2413608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2414608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2415608bcc6dSMat Martineau {
2416608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2417608bcc6dSMat Martineau 	       event);
2418608bcc6dSMat Martineau 
2419608bcc6dSMat Martineau 	switch (event) {
2420608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2421608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2422608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2423608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2424608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2425608bcc6dSMat Martineau 		break;
2426608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2427608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2428608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2429608bcc6dSMat Martineau 
2430608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2431608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2432608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2433608bcc6dSMat Martineau 			 */
2434608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2435608bcc6dSMat Martineau 		}
2436608bcc6dSMat Martineau 
2437608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2438608bcc6dSMat Martineau 
2439608bcc6dSMat Martineau 		break;
2440608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2441608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2442608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2443608bcc6dSMat Martineau 
2444608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2445608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2446608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2447608bcc6dSMat Martineau 			local_control.sframe = 1;
2448608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2449608bcc6dSMat Martineau 			local_control.poll = 1;
2450608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2451a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2452608bcc6dSMat Martineau 
2453608bcc6dSMat Martineau 			chan->retry_count = 1;
2454608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2455608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2456608bcc6dSMat Martineau 		}
2457608bcc6dSMat Martineau 		break;
2458608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2459608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2460608bcc6dSMat Martineau 
2461608bcc6dSMat Martineau 		/* Fall through */
2462608bcc6dSMat Martineau 
2463608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2464608bcc6dSMat Martineau 		if (control && control->final) {
2465608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2466608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2467608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2468608bcc6dSMat Martineau 			chan->retry_count = 0;
2469608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2470608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2471608bcc6dSMat Martineau 		}
2472608bcc6dSMat Martineau 		break;
2473608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2474608bcc6dSMat Martineau 		/* Ignore */
2475608bcc6dSMat Martineau 		break;
2476608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2477608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2478608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2479608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2480608bcc6dSMat Martineau 			chan->retry_count++;
2481608bcc6dSMat Martineau 		} else {
2482608bcc6dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2483608bcc6dSMat Martineau 		}
2484608bcc6dSMat Martineau 		break;
2485608bcc6dSMat Martineau 	default:
2486608bcc6dSMat Martineau 		break;
2487608bcc6dSMat Martineau 	}
2488608bcc6dSMat Martineau }
2489608bcc6dSMat Martineau 
2490d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2491608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2492608bcc6dSMat Martineau {
2493608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2494608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2495608bcc6dSMat Martineau 
2496608bcc6dSMat Martineau 	switch (chan->tx_state) {
2497608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2498d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2499608bcc6dSMat Martineau 		break;
2500608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2501d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2502608bcc6dSMat Martineau 		break;
2503608bcc6dSMat Martineau 	default:
2504608bcc6dSMat Martineau 		/* Ignore event */
2505608bcc6dSMat Martineau 		break;
2506608bcc6dSMat Martineau 	}
2507608bcc6dSMat Martineau }
2508608bcc6dSMat Martineau 
25094b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
25104b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
25114b51dae9SMat Martineau {
25124b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2513401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
25144b51dae9SMat Martineau }
25154b51dae9SMat Martineau 
2516f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2517f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2518f80842a8SMat Martineau {
2519f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2520401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2521f80842a8SMat Martineau }
2522f80842a8SMat Martineau 
25230a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
25240a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
25250a708f8fSGustavo F. Padovan {
25260a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
252748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
25280a708f8fSGustavo F. Padovan 
25290a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
25300a708f8fSGustavo F. Padovan 
25313df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
25323d57dc68SGustavo F. Padovan 
25333df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
253448454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2535715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
25360a708f8fSGustavo F. Padovan 			continue;
25370a708f8fSGustavo F. Padovan 
25380a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
25390a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
25400a708f8fSGustavo F. Padovan 			continue;
25410a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
25420a708f8fSGustavo F. Padovan 		if (!nskb)
25430a708f8fSGustavo F. Padovan 			continue;
25440a708f8fSGustavo F. Padovan 
254580b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
25460a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
25470a708f8fSGustavo F. Padovan 	}
25483d57dc68SGustavo F. Padovan 
25493df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
25500a708f8fSGustavo F. Padovan }
25510a708f8fSGustavo F. Padovan 
25520a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
2553b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
2554b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
25550a708f8fSGustavo F. Padovan {
25560a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
25570a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
25580a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
25590a708f8fSGustavo F. Padovan 	int len, count;
25600a708f8fSGustavo F. Padovan 
2561b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
25620a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
25630a708f8fSGustavo F. Padovan 
25640a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
25650a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
25660a708f8fSGustavo F. Padovan 
25670a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
25680a708f8fSGustavo F. Padovan 	if (!skb)
25690a708f8fSGustavo F. Padovan 		return NULL;
25700a708f8fSGustavo F. Padovan 
25710a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
25720a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
25733300d9a9SClaudio Takahasi 
25743300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
2575ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
25763300d9a9SClaudio Takahasi 	else
2577ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
25780a708f8fSGustavo F. Padovan 
25790a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
25800a708f8fSGustavo F. Padovan 	cmd->code  = code;
25810a708f8fSGustavo F. Padovan 	cmd->ident = ident;
25820a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
25830a708f8fSGustavo F. Padovan 
25840a708f8fSGustavo F. Padovan 	if (dlen) {
25850a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
25860a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
25870a708f8fSGustavo F. Padovan 		data += count;
25880a708f8fSGustavo F. Padovan 	}
25890a708f8fSGustavo F. Padovan 
25900a708f8fSGustavo F. Padovan 	len -= skb->len;
25910a708f8fSGustavo F. Padovan 
25920a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
25930a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
25940a708f8fSGustavo F. Padovan 	while (len) {
25950a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
25960a708f8fSGustavo F. Padovan 
25970a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
25980a708f8fSGustavo F. Padovan 		if (!*frag)
25990a708f8fSGustavo F. Padovan 			goto fail;
26000a708f8fSGustavo F. Padovan 
26010a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
26020a708f8fSGustavo F. Padovan 
26030a708f8fSGustavo F. Padovan 		len  -= count;
26040a708f8fSGustavo F. Padovan 		data += count;
26050a708f8fSGustavo F. Padovan 
26060a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
26070a708f8fSGustavo F. Padovan 	}
26080a708f8fSGustavo F. Padovan 
26090a708f8fSGustavo F. Padovan 	return skb;
26100a708f8fSGustavo F. Padovan 
26110a708f8fSGustavo F. Padovan fail:
26120a708f8fSGustavo F. Padovan 	kfree_skb(skb);
26130a708f8fSGustavo F. Padovan 	return NULL;
26140a708f8fSGustavo F. Padovan }
26150a708f8fSGustavo F. Padovan 
26160a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
26170a708f8fSGustavo F. Padovan {
26180a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26190a708f8fSGustavo F. Padovan 	int len;
26200a708f8fSGustavo F. Padovan 
26210a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
26220a708f8fSGustavo F. Padovan 	*ptr += len;
26230a708f8fSGustavo F. Padovan 
26240a708f8fSGustavo F. Padovan 	*type = opt->type;
26250a708f8fSGustavo F. Padovan 	*olen = opt->len;
26260a708f8fSGustavo F. Padovan 
26270a708f8fSGustavo F. Padovan 	switch (opt->len) {
26280a708f8fSGustavo F. Padovan 	case 1:
26290a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
26300a708f8fSGustavo F. Padovan 		break;
26310a708f8fSGustavo F. Padovan 
26320a708f8fSGustavo F. Padovan 	case 2:
26330a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
26340a708f8fSGustavo F. Padovan 		break;
26350a708f8fSGustavo F. Padovan 
26360a708f8fSGustavo F. Padovan 	case 4:
26370a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
26380a708f8fSGustavo F. Padovan 		break;
26390a708f8fSGustavo F. Padovan 
26400a708f8fSGustavo F. Padovan 	default:
26410a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
26420a708f8fSGustavo F. Padovan 		break;
26430a708f8fSGustavo F. Padovan 	}
26440a708f8fSGustavo F. Padovan 
2645b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
26460a708f8fSGustavo F. Padovan 	return len;
26470a708f8fSGustavo F. Padovan }
26480a708f8fSGustavo F. Padovan 
26490a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
26500a708f8fSGustavo F. Padovan {
26510a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26520a708f8fSGustavo F. Padovan 
2653b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
26540a708f8fSGustavo F. Padovan 
26550a708f8fSGustavo F. Padovan 	opt->type = type;
26560a708f8fSGustavo F. Padovan 	opt->len  = len;
26570a708f8fSGustavo F. Padovan 
26580a708f8fSGustavo F. Padovan 	switch (len) {
26590a708f8fSGustavo F. Padovan 	case 1:
26600a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
26610a708f8fSGustavo F. Padovan 		break;
26620a708f8fSGustavo F. Padovan 
26630a708f8fSGustavo F. Padovan 	case 2:
26640a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
26650a708f8fSGustavo F. Padovan 		break;
26660a708f8fSGustavo F. Padovan 
26670a708f8fSGustavo F. Padovan 	case 4:
26680a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
26690a708f8fSGustavo F. Padovan 		break;
26700a708f8fSGustavo F. Padovan 
26710a708f8fSGustavo F. Padovan 	default:
26720a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
26730a708f8fSGustavo F. Padovan 		break;
26740a708f8fSGustavo F. Padovan 	}
26750a708f8fSGustavo F. Padovan 
26760a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
26770a708f8fSGustavo F. Padovan }
26780a708f8fSGustavo F. Padovan 
2679f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2680f89cef09SAndrei Emeltchenko {
2681f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2682f89cef09SAndrei Emeltchenko 
2683f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2684f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2685f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2686f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2687f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2688f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2689ac73498cSAndrei Emeltchenko 		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2690ac73498cSAndrei Emeltchenko 		efs.flush_to	= __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2691f89cef09SAndrei Emeltchenko 		break;
2692f89cef09SAndrei Emeltchenko 
2693f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2694f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2695f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2696f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2697f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2698f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2699f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2700f89cef09SAndrei Emeltchenko 		break;
2701f89cef09SAndrei Emeltchenko 
2702f89cef09SAndrei Emeltchenko 	default:
2703f89cef09SAndrei Emeltchenko 		return;
2704f89cef09SAndrei Emeltchenko 	}
2705f89cef09SAndrei Emeltchenko 
2706f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2707f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2708f89cef09SAndrei Emeltchenko }
2709f89cef09SAndrei Emeltchenko 
2710721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
27110a708f8fSGustavo F. Padovan {
2712721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2713721c4181SGustavo F. Padovan 					       ack_timer.work);
27140362520bSMat Martineau 	u16 frames_to_ack;
27150a708f8fSGustavo F. Padovan 
27162fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27172fb9b3d4SGustavo F. Padovan 
27186be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
27196be36555SAndrei Emeltchenko 
27200362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
27210362520bSMat Martineau 				     chan->last_acked_seq);
27220362520bSMat Martineau 
27230362520bSMat Martineau 	if (frames_to_ack)
27240362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
27256be36555SAndrei Emeltchenko 
27266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
272709bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
27280a708f8fSGustavo F. Padovan }
27290a708f8fSGustavo F. Padovan 
2730466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
27310a708f8fSGustavo F. Padovan {
27323c588192SMat Martineau 	int err;
27333c588192SMat Martineau 
2734105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2735105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
273642e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
27376a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
273842e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
27396a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2740105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2741105bdf9eSMat Martineau 	chan->sdu = NULL;
2742105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2743105bdf9eSMat Martineau 	chan->sdu_len = 0;
2744105bdf9eSMat Martineau 
2745d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2746d34c34fbSMat Martineau 
2747105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2748105bdf9eSMat Martineau 		return 0;
2749105bdf9eSMat Martineau 
2750105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2751105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
27520a708f8fSGustavo F. Padovan 
2753721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2754721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2755721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
27560a708f8fSGustavo F. Padovan 
2757f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
27580a708f8fSGustavo F. Padovan 
27593c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
27603c588192SMat Martineau 	if (err < 0)
27613c588192SMat Martineau 		return err;
27623c588192SMat Martineau 
27639dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
27649dc9affcSMat Martineau 	if (err < 0)
27659dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
27669dc9affcSMat Martineau 
27679dc9affcSMat Martineau 	return err;
27680a708f8fSGustavo F. Padovan }
27690a708f8fSGustavo F. Padovan 
27700a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
27710a708f8fSGustavo F. Padovan {
27720a708f8fSGustavo F. Padovan 	switch (mode) {
27730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
27740a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27750a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
27760a708f8fSGustavo F. Padovan 			return mode;
27770a708f8fSGustavo F. Padovan 		/* fall through */
27780a708f8fSGustavo F. Padovan 	default:
27790a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
27800a708f8fSGustavo F. Padovan 	}
27810a708f8fSGustavo F. Padovan }
27820a708f8fSGustavo F. Padovan 
27836327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
27846327eb98SAndrei Emeltchenko {
27856327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
27866327eb98SAndrei Emeltchenko }
27876327eb98SAndrei Emeltchenko 
2788f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2789f89cef09SAndrei Emeltchenko {
2790f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2791f89cef09SAndrei Emeltchenko }
2792f89cef09SAndrei Emeltchenko 
27936327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
27946327eb98SAndrei Emeltchenko {
27956327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2796836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
27976327eb98SAndrei Emeltchenko 		/* use extended control field */
27986327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2799836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2800836be934SAndrei Emeltchenko 	} else {
28016327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
28026327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2803836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2804836be934SAndrei Emeltchenko 	}
2805c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
28066327eb98SAndrei Emeltchenko }
28076327eb98SAndrei Emeltchenko 
2808710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
28090a708f8fSGustavo F. Padovan {
28100a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
28110c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
28120a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2813c8f79162SAndrei Emeltchenko 	u16 size;
28140a708f8fSGustavo F. Padovan 
281549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
28160a708f8fSGustavo F. Padovan 
281773ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
28180a708f8fSGustavo F. Padovan 		goto done;
28190a708f8fSGustavo F. Padovan 
28200c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28210a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28220a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2823c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
28240a708f8fSGustavo F. Padovan 			break;
28250a708f8fSGustavo F. Padovan 
2826f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2827f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2828f89cef09SAndrei Emeltchenko 
28290a708f8fSGustavo F. Padovan 		/* fall through */
28300a708f8fSGustavo F. Padovan 	default:
28318c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
28320a708f8fSGustavo F. Padovan 		break;
28330a708f8fSGustavo F. Padovan 	}
28340a708f8fSGustavo F. Padovan 
28350a708f8fSGustavo F. Padovan done:
28360c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
28370c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
28380a708f8fSGustavo F. Padovan 
28390c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28400a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
28418c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
28428c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
28430a708f8fSGustavo F. Padovan 			break;
28440a708f8fSGustavo F. Padovan 
28450a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
28460a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
28470a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
28480a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28490a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
28500a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
28510a708f8fSGustavo F. Padovan 
28520a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28530a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28540a708f8fSGustavo F. Padovan 		break;
28550a708f8fSGustavo F. Padovan 
28560a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
28570a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
285847d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
28590a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28600a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2861c8f79162SAndrei Emeltchenko 
2862c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2863c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2864c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2865c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2866c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
28670a708f8fSGustavo F. Padovan 
28686327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
28696327eb98SAndrei Emeltchenko 
28706327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
28716327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
28720a708f8fSGustavo F. Padovan 
28730a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28740a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28750a708f8fSGustavo F. Padovan 
2876f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2877f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2878f89cef09SAndrei Emeltchenko 
28798c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
28800a708f8fSGustavo F. Padovan 			break;
28810a708f8fSGustavo F. Padovan 
288247d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2883c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
288447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
288547d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
28860a708f8fSGustavo F. Padovan 		}
28876327eb98SAndrei Emeltchenko 
28886327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
28896327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
28906327eb98SAndrei Emeltchenko 								chan->tx_win);
28910a708f8fSGustavo F. Padovan 		break;
28920a708f8fSGustavo F. Padovan 
28930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
2894273759e2SMat Martineau 		l2cap_txwin_setup(chan);
28950a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
28960a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
28970a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
28980a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28990a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2900c8f79162SAndrei Emeltchenko 
2901c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2902c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2903c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2904c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2905c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
29060a708f8fSGustavo F. Padovan 
29070a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
29080a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
29090a708f8fSGustavo F. Padovan 
2910f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2911f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2912f89cef09SAndrei Emeltchenko 
29138c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29140a708f8fSGustavo F. Padovan 			break;
29150a708f8fSGustavo F. Padovan 
291647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2917c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
291847d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
291947d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29200a708f8fSGustavo F. Padovan 		}
29210a708f8fSGustavo F. Padovan 		break;
29220a708f8fSGustavo F. Padovan 	}
29230a708f8fSGustavo F. Padovan 
2924fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
292559e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
29260a708f8fSGustavo F. Padovan 
29270a708f8fSGustavo F. Padovan 	return ptr - data;
29280a708f8fSGustavo F. Padovan }
29290a708f8fSGustavo F. Padovan 
293073ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
29310a708f8fSGustavo F. Padovan {
29320a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
29330a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
293473ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
293573ffa904SGustavo F. Padovan 	int len = chan->conf_len;
29360a708f8fSGustavo F. Padovan 	int type, hint, olen;
29370a708f8fSGustavo F. Padovan 	unsigned long val;
29380a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
293942dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
294042dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
29410a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
29420a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2943c8f79162SAndrei Emeltchenko 	u16 size;
29440a708f8fSGustavo F. Padovan 
294573ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
29460a708f8fSGustavo F. Padovan 
29470a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29480a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
29490a708f8fSGustavo F. Padovan 
29500a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
29510a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
29520a708f8fSGustavo F. Padovan 
29530a708f8fSGustavo F. Padovan 		switch (type) {
29540a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
29550a708f8fSGustavo F. Padovan 			mtu = val;
29560a708f8fSGustavo F. Padovan 			break;
29570a708f8fSGustavo F. Padovan 
29580a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
29590c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
29600a708f8fSGustavo F. Padovan 			break;
29610a708f8fSGustavo F. Padovan 
29620a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
29630a708f8fSGustavo F. Padovan 			break;
29640a708f8fSGustavo F. Padovan 
29650a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29660a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29670a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
29680a708f8fSGustavo F. Padovan 			break;
29690a708f8fSGustavo F. Padovan 
29700a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
29710a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2972c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
297342dceae2SAndrei Emeltchenko 			break;
29740a708f8fSGustavo F. Padovan 
297542dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
297642dceae2SAndrei Emeltchenko 			remote_efs = 1;
297742dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
297842dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
29790a708f8fSGustavo F. Padovan 			break;
29800a708f8fSGustavo F. Padovan 
29816327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
29826327eb98SAndrei Emeltchenko 			if (!enable_hs)
29836327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
29846327eb98SAndrei Emeltchenko 
29856327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
29866327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
2987836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
29886327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
29890a708f8fSGustavo F. Padovan 			break;
29900a708f8fSGustavo F. Padovan 
29910a708f8fSGustavo F. Padovan 		default:
29920a708f8fSGustavo F. Padovan 			if (hint)
29930a708f8fSGustavo F. Padovan 				break;
29940a708f8fSGustavo F. Padovan 
29950a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
29960a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
29970a708f8fSGustavo F. Padovan 			break;
29980a708f8fSGustavo F. Padovan 		}
29990a708f8fSGustavo F. Padovan 	}
30000a708f8fSGustavo F. Padovan 
300173ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
30020a708f8fSGustavo F. Padovan 		goto done;
30030a708f8fSGustavo F. Padovan 
30040c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
30050a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
30060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3007c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
30080c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
30098c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
30100a708f8fSGustavo F. Padovan 			break;
30110a708f8fSGustavo F. Padovan 		}
30120a708f8fSGustavo F. Padovan 
301342dceae2SAndrei Emeltchenko 		if (remote_efs) {
301442dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
301542dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
301642dceae2SAndrei Emeltchenko 			else
301742dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
301842dceae2SAndrei Emeltchenko 		}
301942dceae2SAndrei Emeltchenko 
30200c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
30210a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30220a708f8fSGustavo F. Padovan 
30230a708f8fSGustavo F. Padovan 		break;
30240a708f8fSGustavo F. Padovan 	}
30250a708f8fSGustavo F. Padovan 
30260a708f8fSGustavo F. Padovan done:
30270c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
30280a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
30290c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
30300a708f8fSGustavo F. Padovan 
303173ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
30320a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30330a708f8fSGustavo F. Padovan 
30340a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
30350a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
30360a708f8fSGustavo F. Padovan 	}
30370a708f8fSGustavo F. Padovan 
30380a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
30390a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
30400a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
30410a708f8fSGustavo F. Padovan 
30420a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
30430a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
30440a708f8fSGustavo F. Padovan 		else {
30450c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3046c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
30470a708f8fSGustavo F. Padovan 		}
30480c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
30490a708f8fSGustavo F. Padovan 
305042dceae2SAndrei Emeltchenko 		if (remote_efs) {
305142dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
305242dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
305342dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
305442dceae2SAndrei Emeltchenko 
305542dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
305642dceae2SAndrei Emeltchenko 
305742dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
305842dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
305942dceae2SAndrei Emeltchenko 
306042dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
306142dceae2SAndrei Emeltchenko 							sizeof(efs),
306242dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
30630e8b207eSAndrei Emeltchenko 			} else {
30643e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
30650e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
30660e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
306742dceae2SAndrei Emeltchenko 			}
306842dceae2SAndrei Emeltchenko 		}
306942dceae2SAndrei Emeltchenko 
30700a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
30710a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
307247d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3073c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
30740a708f8fSGustavo F. Padovan 			break;
30750a708f8fSGustavo F. Padovan 
30760a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
30776327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
30782c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
30796327eb98SAndrei Emeltchenko 			else
30806327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
30816327eb98SAndrei Emeltchenko 
30822c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
30830a708f8fSGustavo F. Padovan 
3084c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3085c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3086c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3087c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3088c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3089c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3090c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
30910a708f8fSGustavo F. Padovan 
30920a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
30934fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
30940a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
30954fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
30960a708f8fSGustavo F. Padovan 
3097c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
30980a708f8fSGustavo F. Padovan 
30990a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31000a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31010a708f8fSGustavo F. Padovan 
310242dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
310342dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
310442dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
310542dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
310642dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
310742dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
310842dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
310942dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
311042dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
311142dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
311242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
311342dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
311442dceae2SAndrei Emeltchenko 			}
31150a708f8fSGustavo F. Padovan 			break;
31160a708f8fSGustavo F. Padovan 
31170a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3118c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3119c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3120c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3121c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3122c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3123c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3124c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31250a708f8fSGustavo F. Padovan 
3126c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31270a708f8fSGustavo F. Padovan 
31280a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31290a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31300a708f8fSGustavo F. Padovan 
31310a708f8fSGustavo F. Padovan 			break;
31320a708f8fSGustavo F. Padovan 
31330a708f8fSGustavo F. Padovan 		default:
31340a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
31350a708f8fSGustavo F. Padovan 
31360a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
31370c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
31380a708f8fSGustavo F. Padovan 		}
31390a708f8fSGustavo F. Padovan 
31400a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3141c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
31420a708f8fSGustavo F. Padovan 	}
3143fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
31440a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
314559e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
31460a708f8fSGustavo F. Padovan 
31470a708f8fSGustavo F. Padovan 	return ptr - data;
31480a708f8fSGustavo F. Padovan }
31490a708f8fSGustavo F. Padovan 
3150b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
31510a708f8fSGustavo F. Padovan {
31520a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
31530a708f8fSGustavo F. Padovan 	void *ptr = req->data;
31540a708f8fSGustavo F. Padovan 	int type, olen;
31550a708f8fSGustavo F. Padovan 	unsigned long val;
315636e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
315766af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
31580a708f8fSGustavo F. Padovan 
3159fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
31600a708f8fSGustavo F. Padovan 
31610a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
31620a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
31630a708f8fSGustavo F. Padovan 
31640a708f8fSGustavo F. Padovan 		switch (type) {
31650a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
31660a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
31670a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
31680c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
31690a708f8fSGustavo F. Padovan 			} else
31700c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
31710c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
31720a708f8fSGustavo F. Padovan 			break;
31730a708f8fSGustavo F. Padovan 
31740a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
31750c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
31760a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
31770c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
31780a708f8fSGustavo F. Padovan 			break;
31790a708f8fSGustavo F. Padovan 
31800a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
31810a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
31820a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
31830a708f8fSGustavo F. Padovan 
3184c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
31850c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
31860a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
31870a708f8fSGustavo F. Padovan 
318847d1ec61SGustavo F. Padovan 			chan->fcs = 0;
31890a708f8fSGustavo F. Padovan 
31900a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31910a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31920a708f8fSGustavo F. Padovan 			break;
31936327eb98SAndrei Emeltchenko 
31946327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3195c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
31963e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
31973e6b3b95SGustavo F. Padovan 					   chan->tx_win);
31986327eb98SAndrei Emeltchenko 			break;
319966af7aafSAndrei Emeltchenko 
320066af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
320166af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
320266af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
320366af7aafSAndrei Emeltchenko 
320466af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
320566af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
320666af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
320766af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
320866af7aafSAndrei Emeltchenko 
320966af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
321066af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
321166af7aafSAndrei Emeltchenko 			break;
32120a708f8fSGustavo F. Padovan 		}
32130a708f8fSGustavo F. Padovan 	}
32140a708f8fSGustavo F. Padovan 
32150c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
32160a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
32170a708f8fSGustavo F. Padovan 
32180c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
32190a708f8fSGustavo F. Padovan 
32200e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
32210a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
32220a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
322347d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
322447d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
322547d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3226c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3227c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3228c20f8e35SMat Martineau 						      rfc.txwin_size);
322966af7aafSAndrei Emeltchenko 
323066af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
323166af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
323266af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
323366af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
323466af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
323566af7aafSAndrei Emeltchenko 				chan->local_flush_to =
323666af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
323766af7aafSAndrei Emeltchenko 			}
32380a708f8fSGustavo F. Padovan 			break;
323966af7aafSAndrei Emeltchenko 
32400a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
324147d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
32420a708f8fSGustavo F. Padovan 		}
32430a708f8fSGustavo F. Padovan 	}
32440a708f8fSGustavo F. Padovan 
3245fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
324659e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
32470a708f8fSGustavo F. Padovan 
32480a708f8fSGustavo F. Padovan 	return ptr - data;
32490a708f8fSGustavo F. Padovan }
32500a708f8fSGustavo F. Padovan 
3251fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
32520a708f8fSGustavo F. Padovan {
32530a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
32540a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
32550a708f8fSGustavo F. Padovan 
3256fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32570a708f8fSGustavo F. Padovan 
3258fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
32590a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
32600a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
32610a708f8fSGustavo F. Padovan 
32620a708f8fSGustavo F. Padovan 	return ptr - data;
32630a708f8fSGustavo F. Padovan }
32640a708f8fSGustavo F. Padovan 
32658c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3266710f9b0aSGustavo F. Padovan {
3267710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
32688c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3269710f9b0aSGustavo F. Padovan 	u8 buf[128];
3270710f9b0aSGustavo F. Padovan 
3271fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3272fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3273ac73498cSAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3274ac73498cSAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3275710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
3276710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3277710f9b0aSGustavo F. Padovan 
3278c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3279710f9b0aSGustavo F. Padovan 		return;
3280710f9b0aSGustavo F. Padovan 
3281710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3282710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
3283710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3284710f9b0aSGustavo F. Padovan }
3285710f9b0aSGustavo F. Padovan 
328647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
32870a708f8fSGustavo F. Padovan {
32880a708f8fSGustavo F. Padovan 	int type, olen;
32890a708f8fSGustavo F. Padovan 	unsigned long val;
3290c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3291c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3292c20f8e35SMat Martineau 	 */
3293c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3294c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3295c20f8e35SMat Martineau 		.mode = chan->mode,
3296c20f8e35SMat Martineau 		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3297c20f8e35SMat Martineau 		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3298c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3299c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3300c20f8e35SMat Martineau 	};
33010a708f8fSGustavo F. Padovan 
330247d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
33030a708f8fSGustavo F. Padovan 
33040c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
33050a708f8fSGustavo F. Padovan 		return;
33060a708f8fSGustavo F. Padovan 
33070a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33080a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
33090a708f8fSGustavo F. Padovan 
3310c20f8e35SMat Martineau 		switch (type) {
3311c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3312c20f8e35SMat Martineau 			if (olen == sizeof(rfc))
33130a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
3314c20f8e35SMat Martineau 			break;
3315c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3316c20f8e35SMat Martineau 			txwin_ext = val;
3317c20f8e35SMat Martineau 			break;
3318c20f8e35SMat Martineau 		}
33190a708f8fSGustavo F. Padovan 	}
33200a708f8fSGustavo F. Padovan 
33210a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
33220a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
332347d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
332447d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
332547d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3326c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3327c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3328c20f8e35SMat Martineau 		else
3329c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3330c20f8e35SMat Martineau 					      rfc.txwin_size);
33310a708f8fSGustavo F. Padovan 		break;
33320a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
333347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33340a708f8fSGustavo F. Padovan 	}
33350a708f8fSGustavo F. Padovan }
33360a708f8fSGustavo F. Padovan 
33370a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33380a708f8fSGustavo F. Padovan {
3339e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
33400a708f8fSGustavo F. Padovan 
3341e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
33420a708f8fSGustavo F. Padovan 		return 0;
33430a708f8fSGustavo F. Padovan 
33440a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
33450a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
334617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
33470a708f8fSGustavo F. Padovan 
33480a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
33490a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
33500a708f8fSGustavo F. Padovan 
33510a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
33520a708f8fSGustavo F. Padovan 	}
33530a708f8fSGustavo F. Padovan 
33540a708f8fSGustavo F. Padovan 	return 0;
33550a708f8fSGustavo F. Padovan }
33560a708f8fSGustavo F. Padovan 
33570a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33580a708f8fSGustavo F. Padovan {
33590a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
33600a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
336123691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
33620a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
33630a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
33640a708f8fSGustavo F. Padovan 
33650a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
33660a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
33670a708f8fSGustavo F. Padovan 
3368097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
33690a708f8fSGustavo F. Padovan 
33700a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
3371c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
337223691d75SGustavo F. Padovan 	if (!pchan) {
33730a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
33740a708f8fSGustavo F. Padovan 		goto sendresp;
33750a708f8fSGustavo F. Padovan 	}
33760a708f8fSGustavo F. Padovan 
337723691d75SGustavo F. Padovan 	parent = pchan->sk;
337823691d75SGustavo F. Padovan 
33793df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3380aa2ac881SGustavo F. Padovan 	lock_sock(parent);
33810a708f8fSGustavo F. Padovan 
33820a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
33832983fd68SAndrei Emeltchenko 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
33840a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
33859f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
33860a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
33870a708f8fSGustavo F. Padovan 		goto response;
33880a708f8fSGustavo F. Padovan 	}
33890a708f8fSGustavo F. Padovan 
33900a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
33910a708f8fSGustavo F. Padovan 
33922dfa1003SGustavo Padovan 	/* Check if we already have channel with that dcid */
33932dfa1003SGustavo Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid))
33942dfa1003SGustavo Padovan 		goto response;
33952dfa1003SGustavo Padovan 
339680b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
339780808e43SGustavo F. Padovan 	if (!chan)
33980a708f8fSGustavo F. Padovan 		goto response;
33990a708f8fSGustavo F. Padovan 
340080808e43SGustavo F. Padovan 	sk = chan->sk;
340180808e43SGustavo F. Padovan 
34020a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
34030a708f8fSGustavo F. Padovan 
34040a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
34050a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3406fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3407fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
34080a708f8fSGustavo F. Padovan 
3409d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3410d1010240SGustavo F. Padovan 
34116be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
341248454079SGustavo F. Padovan 
3413fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
34140a708f8fSGustavo F. Padovan 
3415c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
34160a708f8fSGustavo F. Padovan 
3417fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
34180a708f8fSGustavo F. Padovan 
34190a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3420d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3421c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
34220e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
34230a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
34240a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
34250a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
34260a708f8fSGustavo F. Padovan 			} else {
34270e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
34280a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
34290a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
34300a708f8fSGustavo F. Padovan 			}
34310a708f8fSGustavo F. Padovan 		} else {
34320e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
34330a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
34340a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
34350a708f8fSGustavo F. Padovan 		}
34360a708f8fSGustavo F. Padovan 	} else {
34370e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
34380a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
34390a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
34400a708f8fSGustavo F. Padovan 	}
34410a708f8fSGustavo F. Padovan 
34420a708f8fSGustavo F. Padovan response:
3443aa2ac881SGustavo F. Padovan 	release_sock(parent);
34443df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34450a708f8fSGustavo F. Padovan 
34460a708f8fSGustavo F. Padovan sendresp:
34470a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
34480a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
34490a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
34500a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
34510a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
34520a708f8fSGustavo F. Padovan 
34530a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
34540a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
3455ac73498cSAndrei Emeltchenko 		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
34560a708f8fSGustavo F. Padovan 
34570a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
34580a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
34590a708f8fSGustavo F. Padovan 
3460ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
34610a708f8fSGustavo F. Padovan 
34620a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
34630a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
34640a708f8fSGustavo F. Padovan 	}
34650a708f8fSGustavo F. Padovan 
3466c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
34670a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
34680a708f8fSGustavo F. Padovan 		u8 buf[128];
3469c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
34700a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
347173ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
347273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
34730a708f8fSGustavo F. Padovan 	}
34740a708f8fSGustavo F. Padovan 
34750a708f8fSGustavo F. Padovan 	return 0;
34760a708f8fSGustavo F. Padovan }
34770a708f8fSGustavo F. Padovan 
34780a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
34790a708f8fSGustavo F. Padovan {
34800a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
34810a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
348248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
34830a708f8fSGustavo F. Padovan 	u8 req[128];
34843df91ea2SAndrei Emeltchenko 	int err;
34850a708f8fSGustavo F. Padovan 
34860a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
34870a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
34880a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
34890a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
34900a708f8fSGustavo F. Padovan 
34911b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
34921b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
34930a708f8fSGustavo F. Padovan 
34943df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
34953df91ea2SAndrei Emeltchenko 
34960a708f8fSGustavo F. Padovan 	if (scid) {
34973df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
34983df91ea2SAndrei Emeltchenko 		if (!chan) {
34993df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35003df91ea2SAndrei Emeltchenko 			goto unlock;
35013df91ea2SAndrei Emeltchenko 		}
35020a708f8fSGustavo F. Padovan 	} else {
35033df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
35043df91ea2SAndrei Emeltchenko 		if (!chan) {
35053df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35063df91ea2SAndrei Emeltchenko 			goto unlock;
35073df91ea2SAndrei Emeltchenko 		}
35080a708f8fSGustavo F. Padovan 	}
35090a708f8fSGustavo F. Padovan 
35103df91ea2SAndrei Emeltchenko 	err = 0;
35113df91ea2SAndrei Emeltchenko 
35126be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
351348454079SGustavo F. Padovan 
35140a708f8fSGustavo F. Padovan 	switch (result) {
35150a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
351689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3517fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3518fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3519c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
35200a708f8fSGustavo F. Padovan 
3521c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
35220a708f8fSGustavo F. Padovan 			break;
35230a708f8fSGustavo F. Padovan 
35240a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
352573ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
352673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
35270a708f8fSGustavo F. Padovan 		break;
35280a708f8fSGustavo F. Padovan 
35290a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3530c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
35310a708f8fSGustavo F. Padovan 		break;
35320a708f8fSGustavo F. Padovan 
35330a708f8fSGustavo F. Padovan 	default:
353448454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
35350a708f8fSGustavo F. Padovan 		break;
35360a708f8fSGustavo F. Padovan 	}
35370a708f8fSGustavo F. Padovan 
35386be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
35393df91ea2SAndrei Emeltchenko 
35403df91ea2SAndrei Emeltchenko unlock:
35413df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
35423df91ea2SAndrei Emeltchenko 
35433df91ea2SAndrei Emeltchenko 	return err;
35440a708f8fSGustavo F. Padovan }
35450a708f8fSGustavo F. Padovan 
354647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
35470a708f8fSGustavo F. Padovan {
35480a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
35490a708f8fSGustavo F. Padovan 	 * sides request it.
35500a708f8fSGustavo F. Padovan 	 */
35510c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
355247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3553c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
355447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
35550a708f8fSGustavo F. Padovan }
35560a708f8fSGustavo F. Padovan 
35570a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
35580a708f8fSGustavo F. Padovan {
35590a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
35600a708f8fSGustavo F. Padovan 	u16 dcid, flags;
35610a708f8fSGustavo F. Padovan 	u8 rsp[64];
356248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35633c588192SMat Martineau 	int len, err = 0;
35640a708f8fSGustavo F. Padovan 
35650a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
35660a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
35670a708f8fSGustavo F. Padovan 
35680a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
35690a708f8fSGustavo F. Padovan 
3570baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
357148454079SGustavo F. Padovan 	if (!chan)
35720a708f8fSGustavo F. Padovan 		return -ENOENT;
35730a708f8fSGustavo F. Padovan 
3574033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3575e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
35760a708f8fSGustavo F. Padovan 
3577ac73498cSAndrei Emeltchenko 		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
3578e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3579e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3580e2fd318eSIlia Kolomisnky 
35810a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
35820a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
35830a708f8fSGustavo F. Padovan 		goto unlock;
35840a708f8fSGustavo F. Padovan 	}
35850a708f8fSGustavo F. Padovan 
35860a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
35870a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
35887ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
35890a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3590fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
35910a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
35920a708f8fSGustavo F. Padovan 		goto unlock;
35930a708f8fSGustavo F. Padovan 	}
35940a708f8fSGustavo F. Padovan 
35950a708f8fSGustavo F. Padovan 	/* Store config. */
359673ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
359773ffa904SGustavo F. Padovan 	chan->conf_len += len;
35980a708f8fSGustavo F. Padovan 
359959e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
36000a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
36010a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3602fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36035325e5bbSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, flags), rsp);
36040a708f8fSGustavo F. Padovan 		goto unlock;
36050a708f8fSGustavo F. Padovan 	}
36060a708f8fSGustavo F. Padovan 
36070a708f8fSGustavo F. Padovan 	/* Complete config. */
360873ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
36090a708f8fSGustavo F. Padovan 	if (len < 0) {
3610e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
36110a708f8fSGustavo F. Padovan 		goto unlock;
36120a708f8fSGustavo F. Padovan 	}
36130a708f8fSGustavo F. Padovan 
36140a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
361573ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
36160a708f8fSGustavo F. Padovan 
36170a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
361873ffa904SGustavo F. Padovan 	chan->conf_len = 0;
36190a708f8fSGustavo F. Padovan 
3620c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
36210a708f8fSGustavo F. Padovan 		goto unlock;
36220a708f8fSGustavo F. Padovan 
3623c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
362447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
36250a708f8fSGustavo F. Padovan 
3626105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3627105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
36283c588192SMat Martineau 			err = l2cap_ertm_init(chan);
36290a708f8fSGustavo F. Padovan 
36303c588192SMat Martineau 		if (err < 0)
36313c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
36323c588192SMat Martineau 		else
3633cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
36343c588192SMat Martineau 
36350a708f8fSGustavo F. Padovan 		goto unlock;
36360a708f8fSGustavo F. Padovan 	}
36370a708f8fSGustavo F. Padovan 
3638c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
36390a708f8fSGustavo F. Padovan 		u8 buf[64];
36400a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
364173ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
364273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
36430a708f8fSGustavo F. Padovan 	}
36440a708f8fSGustavo F. Padovan 
36450e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
36460e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
36470e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
36480e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
36490e8b207eSAndrei Emeltchenko 
36500e8b207eSAndrei Emeltchenko 		/* check compatibility */
36510e8b207eSAndrei Emeltchenko 
36520e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
36530e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
36540e8b207eSAndrei Emeltchenko 
36550e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
36560e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
36575325e5bbSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, flags), rsp);
36580e8b207eSAndrei Emeltchenko 	}
36590e8b207eSAndrei Emeltchenko 
36600a708f8fSGustavo F. Padovan unlock:
36616be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36623c588192SMat Martineau 	return err;
36630a708f8fSGustavo F. Padovan }
36640a708f8fSGustavo F. Padovan 
36650a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36660a708f8fSGustavo F. Padovan {
36670a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
36680a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
366948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
367061386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
36713c588192SMat Martineau 	int err = 0;
36720a708f8fSGustavo F. Padovan 
36730a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
36740a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
36750a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
36760a708f8fSGustavo F. Padovan 
367761386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
367861386cbaSAndrei Emeltchenko 	       result, len);
36790a708f8fSGustavo F. Padovan 
3680baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
368148454079SGustavo F. Padovan 	if (!chan)
36820a708f8fSGustavo F. Padovan 		return 0;
36830a708f8fSGustavo F. Padovan 
36840a708f8fSGustavo F. Padovan 	switch (result) {
36850a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
368647d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
36870e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
36880a708f8fSGustavo F. Padovan 		break;
36890a708f8fSGustavo F. Padovan 
36900e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
36910e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
36920e8b207eSAndrei Emeltchenko 
36930e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
36940e8b207eSAndrei Emeltchenko 			char buf[64];
36950e8b207eSAndrei Emeltchenko 
36960e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
36970e8b207eSAndrei Emeltchenko 								buf, &result);
36980e8b207eSAndrei Emeltchenko 			if (len < 0) {
36990e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37000e8b207eSAndrei Emeltchenko 				goto done;
37010e8b207eSAndrei Emeltchenko 			}
37020e8b207eSAndrei Emeltchenko 
37030e8b207eSAndrei Emeltchenko 			/* check compatibility */
37040e8b207eSAndrei Emeltchenko 
37050e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
37060e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37070e8b207eSAndrei Emeltchenko 
37080e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
37090e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
37100e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
37110e8b207eSAndrei Emeltchenko 		}
37120e8b207eSAndrei Emeltchenko 		goto done;
37130e8b207eSAndrei Emeltchenko 
37140a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
371573ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
37160a708f8fSGustavo F. Padovan 			char req[64];
37170a708f8fSGustavo F. Padovan 
37180a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3719e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37200a708f8fSGustavo F. Padovan 				goto done;
37210a708f8fSGustavo F. Padovan 			}
37220a708f8fSGustavo F. Padovan 
37230a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
37240a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3725b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3726b4450035SGustavo F. Padovan 								req, &result);
37270a708f8fSGustavo F. Padovan 			if (len < 0) {
3728e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37290a708f8fSGustavo F. Padovan 				goto done;
37300a708f8fSGustavo F. Padovan 			}
37310a708f8fSGustavo F. Padovan 
37320a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
37330a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
373473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
37350a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
37360a708f8fSGustavo F. Padovan 				goto done;
37370a708f8fSGustavo F. Padovan 			break;
37380a708f8fSGustavo F. Padovan 		}
37390a708f8fSGustavo F. Padovan 
37400a708f8fSGustavo F. Padovan 	default:
37416be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
37422e0052e4SAndrei Emeltchenko 
3743ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3744e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
37450a708f8fSGustavo F. Padovan 		goto done;
37460a708f8fSGustavo F. Padovan 	}
37470a708f8fSGustavo F. Padovan 
374859e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
37490a708f8fSGustavo F. Padovan 		goto done;
37500a708f8fSGustavo F. Padovan 
3751c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
37520a708f8fSGustavo F. Padovan 
3753c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
375447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
37550a708f8fSGustavo F. Padovan 
3756105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3757105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
37583c588192SMat Martineau 			err = l2cap_ertm_init(chan);
37590a708f8fSGustavo F. Padovan 
37603c588192SMat Martineau 		if (err < 0)
37613c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
37623c588192SMat Martineau 		else
3763cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
37640a708f8fSGustavo F. Padovan 	}
37650a708f8fSGustavo F. Padovan 
37660a708f8fSGustavo F. Padovan done:
37676be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
37683c588192SMat Martineau 	return err;
37690a708f8fSGustavo F. Padovan }
37700a708f8fSGustavo F. Padovan 
37710a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
37720a708f8fSGustavo F. Padovan {
37730a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
37740a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
37750a708f8fSGustavo F. Padovan 	u16 dcid, scid;
377648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
37770a708f8fSGustavo F. Padovan 	struct sock *sk;
37780a708f8fSGustavo F. Padovan 
37790a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
37800a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
37810a708f8fSGustavo F. Padovan 
37820a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
37830a708f8fSGustavo F. Padovan 
37843df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
37853df91ea2SAndrei Emeltchenko 
37863df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
37873df91ea2SAndrei Emeltchenko 	if (!chan) {
37883df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
37890a708f8fSGustavo F. Padovan 		return 0;
37903df91ea2SAndrei Emeltchenko 	}
37910a708f8fSGustavo F. Padovan 
37926be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
37936be36555SAndrei Emeltchenko 
379448454079SGustavo F. Padovan 	sk = chan->sk;
379548454079SGustavo F. Padovan 
3796fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3797fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
37980a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
37990a708f8fSGustavo F. Padovan 
38006be36555SAndrei Emeltchenko 	lock_sock(sk);
38010a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
38026be36555SAndrei Emeltchenko 	release_sock(sk);
38030a708f8fSGustavo F. Padovan 
380461d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
380548454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
38066be36555SAndrei Emeltchenko 
38076be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38080a708f8fSGustavo F. Padovan 
380980b98027SGustavo Padovan 	chan->ops->close(chan);
381061d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38113df91ea2SAndrei Emeltchenko 
38123df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38133df91ea2SAndrei Emeltchenko 
38140a708f8fSGustavo F. Padovan 	return 0;
38150a708f8fSGustavo F. Padovan }
38160a708f8fSGustavo F. Padovan 
38170a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38180a708f8fSGustavo F. Padovan {
38190a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
38200a708f8fSGustavo F. Padovan 	u16 dcid, scid;
382148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38220a708f8fSGustavo F. Padovan 
38230a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
38240a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
38250a708f8fSGustavo F. Padovan 
38260a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
38270a708f8fSGustavo F. Padovan 
38283df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38293df91ea2SAndrei Emeltchenko 
38303df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
38313df91ea2SAndrei Emeltchenko 	if (!chan) {
38323df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38330a708f8fSGustavo F. Padovan 		return 0;
38343df91ea2SAndrei Emeltchenko 	}
38350a708f8fSGustavo F. Padovan 
38366be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
383748454079SGustavo F. Padovan 
383861d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
383948454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
38406be36555SAndrei Emeltchenko 
38416be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38420a708f8fSGustavo F. Padovan 
384380b98027SGustavo Padovan 	chan->ops->close(chan);
384461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38453df91ea2SAndrei Emeltchenko 
38463df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38473df91ea2SAndrei Emeltchenko 
38480a708f8fSGustavo F. Padovan 	return 0;
38490a708f8fSGustavo F. Padovan }
38500a708f8fSGustavo F. Padovan 
38510a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38520a708f8fSGustavo F. Padovan {
38530a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
38540a708f8fSGustavo F. Padovan 	u16 type;
38550a708f8fSGustavo F. Padovan 
38560a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
38570a708f8fSGustavo F. Padovan 
38580a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
38590a708f8fSGustavo F. Padovan 
38600a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
38610a708f8fSGustavo F. Padovan 		u8 buf[8];
38620a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
38630a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
3864ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
3865ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
38660a708f8fSGustavo F. Padovan 		if (!disable_ertm)
38670a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
38680a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3869a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
38706327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
38716327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3872a5fd6f30SAndrei Emeltchenko 
38730a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
38740a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
38750a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
38760a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
38770a708f8fSGustavo F. Padovan 		u8 buf[12];
38780a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
387950a147cdSMat Martineau 
388050a147cdSMat Martineau 		if (enable_hs)
388150a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
388250a147cdSMat Martineau 		else
388350a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
388450a147cdSMat Martineau 
3885ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
3886ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
3887c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
38880a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
38890a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
38900a708f8fSGustavo F. Padovan 	} else {
38910a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
38920a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
3893ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
38940a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
38950a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
38960a708f8fSGustavo F. Padovan 	}
38970a708f8fSGustavo F. Padovan 
38980a708f8fSGustavo F. Padovan 	return 0;
38990a708f8fSGustavo F. Padovan }
39000a708f8fSGustavo F. Padovan 
39010a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
39020a708f8fSGustavo F. Padovan {
39030a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
39040a708f8fSGustavo F. Padovan 	u16 type, result;
39050a708f8fSGustavo F. Padovan 
39060a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
39070a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
39080a708f8fSGustavo F. Padovan 
39090a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
39100a708f8fSGustavo F. Padovan 
3911e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3912e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3913e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3914e90165beSAndrei Emeltchenko 		return 0;
3915e90165beSAndrei Emeltchenko 
391617cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
39170a708f8fSGustavo F. Padovan 
39180a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
39190a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39200a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39210a708f8fSGustavo F. Padovan 
39220a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39230a708f8fSGustavo F. Padovan 
39240a708f8fSGustavo F. Padovan 		return 0;
39250a708f8fSGustavo F. Padovan 	}
39260a708f8fSGustavo F. Padovan 
3927978c93b9SAndrei Emeltchenko 	switch (type) {
3928978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
39290a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
39300a708f8fSGustavo F. Padovan 
39310a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
39320a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
3933ac73498cSAndrei Emeltchenko 			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39340a708f8fSGustavo F. Padovan 
39350a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
39360a708f8fSGustavo F. Padovan 
39370a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
39380a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
39390a708f8fSGustavo F. Padovan 		} else {
39400a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39410a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
39420a708f8fSGustavo F. Padovan 
39430a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
39440a708f8fSGustavo F. Padovan 		}
3945978c93b9SAndrei Emeltchenko 		break;
3946978c93b9SAndrei Emeltchenko 
3947978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3948978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
39490a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39500a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39510a708f8fSGustavo F. Padovan 
39520a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3953978c93b9SAndrei Emeltchenko 		break;
39540a708f8fSGustavo F. Padovan 	}
39550a708f8fSGustavo F. Padovan 
39560a708f8fSGustavo F. Padovan 	return 0;
39570a708f8fSGustavo F. Padovan }
39580a708f8fSGustavo F. Padovan 
3959f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3960f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3961f94ff6ffSMat Martineau 					void *data)
3962f94ff6ffSMat Martineau {
3963f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3964f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3965f94ff6ffSMat Martineau 	u16 psm, scid;
3966f94ff6ffSMat Martineau 
3967f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3968f94ff6ffSMat Martineau 		return -EPROTO;
3969f94ff6ffSMat Martineau 
3970f94ff6ffSMat Martineau 	if (!enable_hs)
3971f94ff6ffSMat Martineau 		return -EINVAL;
3972f94ff6ffSMat Martineau 
3973f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3974f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
3975f94ff6ffSMat Martineau 
3976ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
3977f94ff6ffSMat Martineau 
3978f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
3979f94ff6ffSMat Martineau 	rsp.dcid = 0;
3980f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
39818ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
39828ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3983f94ff6ffSMat Martineau 
3984f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
3985f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
3986f94ff6ffSMat Martineau 
3987f94ff6ffSMat Martineau 	return 0;
3988f94ff6ffSMat Martineau }
3989f94ff6ffSMat Martineau 
3990f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
3991f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
3992f94ff6ffSMat Martineau {
3993f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
3994f94ff6ffSMat Martineau 
3995f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
3996f94ff6ffSMat Martineau }
3997f94ff6ffSMat Martineau 
39988d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
39998d5a04a1SMat Martineau 				     u16 icid, u16 result)
40008d5a04a1SMat Martineau {
40018d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
40028d5a04a1SMat Martineau 
4003ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
40048d5a04a1SMat Martineau 
40058d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40068d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
40078d5a04a1SMat Martineau 
40088d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
40098d5a04a1SMat Martineau }
40108d5a04a1SMat Martineau 
40118d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
4012ad0ac6caSAndrei Emeltchenko 				     struct l2cap_chan *chan,
4013ad0ac6caSAndrei Emeltchenko 				     u16 icid, u16 result)
40148d5a04a1SMat Martineau {
40158d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
40168d5a04a1SMat Martineau 	u8 ident;
40178d5a04a1SMat Martineau 
4018ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
40198d5a04a1SMat Martineau 
40208d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
40218d5a04a1SMat Martineau 	if (chan)
40228d5a04a1SMat Martineau 		chan->ident = ident;
40238d5a04a1SMat Martineau 
40248d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
40258d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
40268d5a04a1SMat Martineau 
40278d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
40288d5a04a1SMat Martineau }
40298d5a04a1SMat Martineau 
40308d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
40318d5a04a1SMat Martineau 					 u16 icid)
40328d5a04a1SMat Martineau {
40338d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
40348d5a04a1SMat Martineau 
4035ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
40368d5a04a1SMat Martineau 
40378d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40388d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
40398d5a04a1SMat Martineau }
40408d5a04a1SMat Martineau 
40418d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
4042ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
4043ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
40448d5a04a1SMat Martineau {
40458d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
40468d5a04a1SMat Martineau 	u16 icid = 0;
40478d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
40488d5a04a1SMat Martineau 
40498d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
40508d5a04a1SMat Martineau 		return -EPROTO;
40518d5a04a1SMat Martineau 
40528d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
40538d5a04a1SMat Martineau 
4054ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
40558d5a04a1SMat Martineau 
40568d5a04a1SMat Martineau 	if (!enable_hs)
40578d5a04a1SMat Martineau 		return -EINVAL;
40588d5a04a1SMat Martineau 
40598d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
40608d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
40618d5a04a1SMat Martineau 
40628d5a04a1SMat Martineau 	return 0;
40638d5a04a1SMat Martineau }
40648d5a04a1SMat Martineau 
40658d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
4066ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
4067ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
40688d5a04a1SMat Martineau {
40698d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
40708d5a04a1SMat Martineau 	u16 icid, result;
40718d5a04a1SMat Martineau 
40728d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
40738d5a04a1SMat Martineau 		return -EPROTO;
40748d5a04a1SMat Martineau 
40758d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
40768d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
40778d5a04a1SMat Martineau 
4078ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
40798d5a04a1SMat Martineau 
40808d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
40818d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
40828d5a04a1SMat Martineau 
40838d5a04a1SMat Martineau 	return 0;
40848d5a04a1SMat Martineau }
40858d5a04a1SMat Martineau 
40868d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
4087ad0ac6caSAndrei Emeltchenko 					     struct l2cap_cmd_hdr *cmd,
4088ad0ac6caSAndrei Emeltchenko 					     u16 cmd_len, void *data)
40898d5a04a1SMat Martineau {
40908d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
40918d5a04a1SMat Martineau 	u16 icid, result;
40928d5a04a1SMat Martineau 
40938d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
40948d5a04a1SMat Martineau 		return -EPROTO;
40958d5a04a1SMat Martineau 
40968d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
40978d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
40988d5a04a1SMat Martineau 
4099ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
41008d5a04a1SMat Martineau 
41018d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
41028d5a04a1SMat Martineau 
41038d5a04a1SMat Martineau 	return 0;
41048d5a04a1SMat Martineau }
41058d5a04a1SMat Martineau 
41068d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
4107ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
4108ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
41098d5a04a1SMat Martineau {
41108d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
41118d5a04a1SMat Martineau 	u16 icid;
41128d5a04a1SMat Martineau 
41138d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
41148d5a04a1SMat Martineau 		return -EPROTO;
41158d5a04a1SMat Martineau 
41168d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
41178d5a04a1SMat Martineau 
4118ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
41198d5a04a1SMat Martineau 
41208d5a04a1SMat Martineau 	return 0;
41218d5a04a1SMat Martineau }
41228d5a04a1SMat Martineau 
4123e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
4124de73115aSClaudio Takahasi 							u16 to_multiplier)
4125de73115aSClaudio Takahasi {
4126de73115aSClaudio Takahasi 	u16 max_latency;
4127de73115aSClaudio Takahasi 
4128de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
4129de73115aSClaudio Takahasi 		return -EINVAL;
4130de73115aSClaudio Takahasi 
4131de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
4132de73115aSClaudio Takahasi 		return -EINVAL;
4133de73115aSClaudio Takahasi 
4134de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
4135de73115aSClaudio Takahasi 		return -EINVAL;
4136de73115aSClaudio Takahasi 
4137de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
4138de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
4139de73115aSClaudio Takahasi 		return -EINVAL;
4140de73115aSClaudio Takahasi 
4141de73115aSClaudio Takahasi 	return 0;
4142de73115aSClaudio Takahasi }
4143de73115aSClaudio Takahasi 
4144de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
4145de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
4146de73115aSClaudio Takahasi {
4147de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
4148de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
4149de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
4150de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
41512ce603ebSClaudio Takahasi 	int err;
4152de73115aSClaudio Takahasi 
4153de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
4154de73115aSClaudio Takahasi 		return -EINVAL;
4155de73115aSClaudio Takahasi 
4156de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
4157de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4158de73115aSClaudio Takahasi 		return -EPROTO;
4159de73115aSClaudio Takahasi 
4160de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4161de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4162de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4163de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4164de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4165de73115aSClaudio Takahasi 
4166de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4167de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
4168de73115aSClaudio Takahasi 
4169de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
41702ce603ebSClaudio Takahasi 
41712ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
41722ce603ebSClaudio Takahasi 	if (err)
4173ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4174de73115aSClaudio Takahasi 	else
4175ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4176de73115aSClaudio Takahasi 
4177de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4178de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
4179de73115aSClaudio Takahasi 
41802ce603ebSClaudio Takahasi 	if (!err)
41812ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
41822ce603ebSClaudio Takahasi 
4183de73115aSClaudio Takahasi 	return 0;
4184de73115aSClaudio Takahasi }
4185de73115aSClaudio Takahasi 
41863300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
41873300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
41883300d9a9SClaudio Takahasi {
41893300d9a9SClaudio Takahasi 	int err = 0;
41903300d9a9SClaudio Takahasi 
41913300d9a9SClaudio Takahasi 	switch (cmd->code) {
41923300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
41933300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
41943300d9a9SClaudio Takahasi 		break;
41953300d9a9SClaudio Takahasi 
41963300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
41973300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
41983300d9a9SClaudio Takahasi 		break;
41993300d9a9SClaudio Takahasi 
42003300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
42013300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
42023300d9a9SClaudio Takahasi 		break;
42033300d9a9SClaudio Takahasi 
42043300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
42053300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
42063300d9a9SClaudio Takahasi 		break;
42073300d9a9SClaudio Takahasi 
42083300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
42093300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
42103300d9a9SClaudio Takahasi 		break;
42113300d9a9SClaudio Takahasi 
42123300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
42133300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
42143300d9a9SClaudio Takahasi 		break;
42153300d9a9SClaudio Takahasi 
42163300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
42173300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
42183300d9a9SClaudio Takahasi 		break;
42193300d9a9SClaudio Takahasi 
42203300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
42213300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
42223300d9a9SClaudio Takahasi 		break;
42233300d9a9SClaudio Takahasi 
42243300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
42253300d9a9SClaudio Takahasi 		break;
42263300d9a9SClaudio Takahasi 
42273300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
42283300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
42293300d9a9SClaudio Takahasi 		break;
42303300d9a9SClaudio Takahasi 
42313300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
42323300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
42333300d9a9SClaudio Takahasi 		break;
42343300d9a9SClaudio Takahasi 
4235f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
4236f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4237f94ff6ffSMat Martineau 		break;
4238f94ff6ffSMat Martineau 
4239f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
4240f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
4241f94ff6ffSMat Martineau 		break;
4242f94ff6ffSMat Martineau 
42438d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
42448d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
42458d5a04a1SMat Martineau 		break;
42468d5a04a1SMat Martineau 
42478d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
42488d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
42498d5a04a1SMat Martineau 		break;
42508d5a04a1SMat Martineau 
42518d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
42528d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
42538d5a04a1SMat Martineau 		break;
42548d5a04a1SMat Martineau 
42558d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
42568d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
42578d5a04a1SMat Martineau 		break;
42588d5a04a1SMat Martineau 
42593300d9a9SClaudio Takahasi 	default:
42603300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
42613300d9a9SClaudio Takahasi 		err = -EINVAL;
42623300d9a9SClaudio Takahasi 		break;
42633300d9a9SClaudio Takahasi 	}
42643300d9a9SClaudio Takahasi 
42653300d9a9SClaudio Takahasi 	return err;
42663300d9a9SClaudio Takahasi }
42673300d9a9SClaudio Takahasi 
42683300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
42693300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
42703300d9a9SClaudio Takahasi {
42713300d9a9SClaudio Takahasi 	switch (cmd->code) {
42723300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
42733300d9a9SClaudio Takahasi 		return 0;
42743300d9a9SClaudio Takahasi 
42753300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
4276de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
42773300d9a9SClaudio Takahasi 
42783300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
42793300d9a9SClaudio Takahasi 		return 0;
42803300d9a9SClaudio Takahasi 
42813300d9a9SClaudio Takahasi 	default:
42823300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
42833300d9a9SClaudio Takahasi 		return -EINVAL;
42843300d9a9SClaudio Takahasi 	}
42853300d9a9SClaudio Takahasi }
42863300d9a9SClaudio Takahasi 
42873300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
42883300d9a9SClaudio Takahasi 							struct sk_buff *skb)
42890a708f8fSGustavo F. Padovan {
42900a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
42910a708f8fSGustavo F. Padovan 	int len = skb->len;
42920a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
42933300d9a9SClaudio Takahasi 	int err;
42940a708f8fSGustavo F. Padovan 
42950a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
42960a708f8fSGustavo F. Padovan 
42970a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
42980a708f8fSGustavo F. Padovan 		u16 cmd_len;
42990a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
43000a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
43010a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
43020a708f8fSGustavo F. Padovan 
43030a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
43040a708f8fSGustavo F. Padovan 
43050a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
43060a708f8fSGustavo F. Padovan 
43070a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
43080a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
43090a708f8fSGustavo F. Padovan 			break;
43100a708f8fSGustavo F. Padovan 		}
43110a708f8fSGustavo F. Padovan 
43123300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
43133300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
43143300d9a9SClaudio Takahasi 		else
43153300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
43160a708f8fSGustavo F. Padovan 
43170a708f8fSGustavo F. Padovan 		if (err) {
4318e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
43192c6d1a2eSGustavo F. Padovan 
43202c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
43210a708f8fSGustavo F. Padovan 
43220a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
4323ac73498cSAndrei Emeltchenko 			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
43240a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
43250a708f8fSGustavo F. Padovan 		}
43260a708f8fSGustavo F. Padovan 
43270a708f8fSGustavo F. Padovan 		data += cmd_len;
43280a708f8fSGustavo F. Padovan 		len  -= cmd_len;
43290a708f8fSGustavo F. Padovan 	}
43300a708f8fSGustavo F. Padovan 
43310a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43320a708f8fSGustavo F. Padovan }
43330a708f8fSGustavo F. Padovan 
433447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
43350a708f8fSGustavo F. Padovan {
43360a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
4337e4ca6d98SAndrei Emeltchenko 	int hdr_size;
4338e4ca6d98SAndrei Emeltchenko 
4339e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4340e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
4341e4ca6d98SAndrei Emeltchenko 	else
4342e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
43430a708f8fSGustavo F. Padovan 
434447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
434503a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
43460a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
43470a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
43480a708f8fSGustavo F. Padovan 
43490a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
43500a708f8fSGustavo F. Padovan 			return -EBADMSG;
43510a708f8fSGustavo F. Padovan 	}
43520a708f8fSGustavo F. Padovan 	return 0;
43530a708f8fSGustavo F. Padovan }
43540a708f8fSGustavo F. Padovan 
43556ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
43560a708f8fSGustavo F. Padovan {
4357e31f7633SMat Martineau 	struct l2cap_ctrl control;
43580a708f8fSGustavo F. Padovan 
4359e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
43600a708f8fSGustavo F. Padovan 
4361e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
4362e31f7633SMat Martineau 	control.sframe = 1;
4363e31f7633SMat Martineau 	control.final = 1;
4364e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
4365e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
43660a708f8fSGustavo F. Padovan 
4367e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4368e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
4369e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43700a708f8fSGustavo F. Padovan 	}
43710a708f8fSGustavo F. Padovan 
4372e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4373e31f7633SMat Martineau 	    chan->unacked_frames > 0)
4374e31f7633SMat Martineau 		__set_retrans_timer(chan);
43750a708f8fSGustavo F. Padovan 
4376e31f7633SMat Martineau 	/* Send pending iframes */
4377525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
43780a708f8fSGustavo F. Padovan 
4379e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4380e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4381e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
4382e31f7633SMat Martineau 		 * send it now.
4383e31f7633SMat Martineau 		 */
4384e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
4385e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43860a708f8fSGustavo F. Padovan 	}
43870a708f8fSGustavo F. Padovan }
43880a708f8fSGustavo F. Padovan 
438984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
439084084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
43910a708f8fSGustavo F. Padovan {
439284084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
439384084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
439484084a31SMat Martineau 	 */
439584084a31SMat Martineau 	if (!skb_has_frag_list(skb))
439684084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
439784084a31SMat Martineau 
439884084a31SMat Martineau 	new_frag->next = NULL;
439984084a31SMat Martineau 
440084084a31SMat Martineau 	(*last_frag)->next = new_frag;
440184084a31SMat Martineau 	*last_frag = new_frag;
440284084a31SMat Martineau 
440384084a31SMat Martineau 	skb->len += new_frag->len;
440484084a31SMat Martineau 	skb->data_len += new_frag->len;
440584084a31SMat Martineau 	skb->truesize += new_frag->truesize;
440684084a31SMat Martineau }
440784084a31SMat Martineau 
44084b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
44094b51dae9SMat Martineau 				struct l2cap_ctrl *control)
441084084a31SMat Martineau {
441184084a31SMat Martineau 	int err = -EINVAL;
44120a708f8fSGustavo F. Padovan 
44134b51dae9SMat Martineau 	switch (control->sar) {
44147e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
441584084a31SMat Martineau 		if (chan->sdu)
441684084a31SMat Martineau 			break;
44170a708f8fSGustavo F. Padovan 
441880b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
441984084a31SMat Martineau 		break;
44200a708f8fSGustavo F. Padovan 
44217e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
442284084a31SMat Martineau 		if (chan->sdu)
442384084a31SMat Martineau 			break;
44240a708f8fSGustavo F. Padovan 
44256f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
442603a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
44270a708f8fSGustavo F. Padovan 
442884084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
442984084a31SMat Martineau 			err = -EMSGSIZE;
443084084a31SMat Martineau 			break;
443184084a31SMat Martineau 		}
44320a708f8fSGustavo F. Padovan 
443384084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
443484084a31SMat Martineau 			break;
443584084a31SMat Martineau 
443684084a31SMat Martineau 		chan->sdu = skb;
443784084a31SMat Martineau 		chan->sdu_last_frag = skb;
443884084a31SMat Martineau 
443984084a31SMat Martineau 		skb = NULL;
444084084a31SMat Martineau 		err = 0;
44410a708f8fSGustavo F. Padovan 		break;
44420a708f8fSGustavo F. Padovan 
44437e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
44446f61fd47SGustavo F. Padovan 		if (!chan->sdu)
444584084a31SMat Martineau 			break;
44460a708f8fSGustavo F. Padovan 
444784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
444884084a31SMat Martineau 				&chan->sdu_last_frag);
444984084a31SMat Martineau 		skb = NULL;
44500a708f8fSGustavo F. Padovan 
445184084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
445284084a31SMat Martineau 			break;
44530a708f8fSGustavo F. Padovan 
445484084a31SMat Martineau 		err = 0;
44550a708f8fSGustavo F. Padovan 		break;
44560a708f8fSGustavo F. Padovan 
44577e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
44586f61fd47SGustavo F. Padovan 		if (!chan->sdu)
445984084a31SMat Martineau 			break;
44600a708f8fSGustavo F. Padovan 
446184084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
446284084a31SMat Martineau 				&chan->sdu_last_frag);
446384084a31SMat Martineau 		skb = NULL;
44640a708f8fSGustavo F. Padovan 
446584084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
446684084a31SMat Martineau 			break;
44670a708f8fSGustavo F. Padovan 
446880b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
44690a708f8fSGustavo F. Padovan 
447084084a31SMat Martineau 		if (!err) {
447184084a31SMat Martineau 			/* Reassembly complete */
447284084a31SMat Martineau 			chan->sdu = NULL;
447384084a31SMat Martineau 			chan->sdu_last_frag = NULL;
447484084a31SMat Martineau 			chan->sdu_len = 0;
44750a708f8fSGustavo F. Padovan 		}
44760a708f8fSGustavo F. Padovan 		break;
44770a708f8fSGustavo F. Padovan 	}
44780a708f8fSGustavo F. Padovan 
447984084a31SMat Martineau 	if (err) {
44800a708f8fSGustavo F. Padovan 		kfree_skb(skb);
44816f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
44826f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
448384084a31SMat Martineau 		chan->sdu_last_frag = NULL;
448484084a31SMat Martineau 		chan->sdu_len = 0;
448584084a31SMat Martineau 	}
44860a708f8fSGustavo F. Padovan 
448784084a31SMat Martineau 	return err;
44880a708f8fSGustavo F. Padovan }
44890a708f8fSGustavo F. Padovan 
4490e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
44910a708f8fSGustavo F. Padovan {
449261aa4f5bSMat Martineau 	u8 event;
449361aa4f5bSMat Martineau 
449461aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
449561aa4f5bSMat Martineau 		return;
449661aa4f5bSMat Martineau 
449761aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
4498401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
44990a708f8fSGustavo F. Padovan }
45000a708f8fSGustavo F. Padovan 
4501d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
4502d2a7ac5dSMat Martineau {
450363838725SMat Martineau 	int err = 0;
450463838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
450563838725SMat Martineau 	 * until a gap is encountered.
450663838725SMat Martineau 	 */
450763838725SMat Martineau 
450863838725SMat Martineau 	BT_DBG("chan %p", chan);
450963838725SMat Martineau 
451063838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
451163838725SMat Martineau 		struct sk_buff *skb;
451263838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
451363838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
451463838725SMat Martineau 
451563838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
451663838725SMat Martineau 
451763838725SMat Martineau 		if (!skb)
451863838725SMat Martineau 			break;
451963838725SMat Martineau 
452063838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
452163838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
452263838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
452363838725SMat Martineau 		if (err)
452463838725SMat Martineau 			break;
452563838725SMat Martineau 	}
452663838725SMat Martineau 
452763838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
452863838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
452963838725SMat Martineau 		l2cap_send_ack(chan);
453063838725SMat Martineau 	}
453163838725SMat Martineau 
453263838725SMat Martineau 	return err;
4533d2a7ac5dSMat Martineau }
4534d2a7ac5dSMat Martineau 
4535d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
4536d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
4537d2a7ac5dSMat Martineau {
4538f80842a8SMat Martineau 	struct sk_buff *skb;
4539f80842a8SMat Martineau 
4540f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4541f80842a8SMat Martineau 
4542f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4543f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4544f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4545f80842a8SMat Martineau 		return;
4546f80842a8SMat Martineau 	}
4547f80842a8SMat Martineau 
4548f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4549f80842a8SMat Martineau 
4550f80842a8SMat Martineau 	if (skb == NULL) {
4551f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
4552f80842a8SMat Martineau 		       control->reqseq);
4553f80842a8SMat Martineau 		return;
4554f80842a8SMat Martineau 	}
4555f80842a8SMat Martineau 
4556f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
4557f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4558f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4559f80842a8SMat Martineau 		return;
4560f80842a8SMat Martineau 	}
4561f80842a8SMat Martineau 
4562f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4563f80842a8SMat Martineau 
4564f80842a8SMat Martineau 	if (control->poll) {
4565f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
4566f80842a8SMat Martineau 
4567f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4568f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
4569f80842a8SMat Martineau 		l2cap_ertm_send(chan);
4570f80842a8SMat Martineau 
4571f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4572f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
4573f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
4574f80842a8SMat Martineau 		}
4575f80842a8SMat Martineau 	} else {
4576f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
4577f80842a8SMat Martineau 
4578f80842a8SMat Martineau 		if (control->final) {
4579f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
4580f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
4581f80842a8SMat Martineau 						&chan->conn_state))
4582f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
4583f80842a8SMat Martineau 		} else {
4584f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
4585f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4586f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
4587f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
4588f80842a8SMat Martineau 			}
4589f80842a8SMat Martineau 		}
4590f80842a8SMat Martineau 	}
4591d2a7ac5dSMat Martineau }
4592d2a7ac5dSMat Martineau 
4593d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
4594d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
4595d2a7ac5dSMat Martineau {
4596fcd289dfSMat Martineau 	struct sk_buff *skb;
4597fcd289dfSMat Martineau 
4598fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4599fcd289dfSMat Martineau 
4600fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4601fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4602fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4603fcd289dfSMat Martineau 		return;
4604fcd289dfSMat Martineau 	}
4605fcd289dfSMat Martineau 
4606fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4607fcd289dfSMat Martineau 
4608fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
4609fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
4610fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4611fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4612fcd289dfSMat Martineau 		return;
4613fcd289dfSMat Martineau 	}
4614fcd289dfSMat Martineau 
4615fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4616fcd289dfSMat Martineau 
4617fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
4618fcd289dfSMat Martineau 
4619fcd289dfSMat Martineau 	if (control->final) {
4620fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4621fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
4622fcd289dfSMat Martineau 	} else {
4623fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
4624fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
4625fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
4626fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
4627fcd289dfSMat Martineau 	}
4628d2a7ac5dSMat Martineau }
4629d2a7ac5dSMat Martineau 
46304b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
46314b51dae9SMat Martineau {
46324b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
46334b51dae9SMat Martineau 
46344b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
46354b51dae9SMat Martineau 	       chan->expected_tx_seq);
46364b51dae9SMat Martineau 
46374b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
46384b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46394b51dae9SMat Martineau 								chan->tx_win) {
46404b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
46414b51dae9SMat Martineau 			 * invalid packets.
46424b51dae9SMat Martineau 			 */
46434b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
46444b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
46454b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
46464b51dae9SMat Martineau 			} else {
46474b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
46484b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
46494b51dae9SMat Martineau 			}
46504b51dae9SMat Martineau 		}
46514b51dae9SMat Martineau 
46524b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
46534b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
46544b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
46554b51dae9SMat Martineau 		}
46564b51dae9SMat Martineau 
46574b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
46584b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
46594b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
46604b51dae9SMat Martineau 		}
46614b51dae9SMat Martineau 
46624b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
46634b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
46644b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
46654b51dae9SMat Martineau 		}
46664b51dae9SMat Martineau 	}
46674b51dae9SMat Martineau 
46684b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
46694b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46704b51dae9SMat Martineau 		    chan->tx_win) {
46714b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
46724b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
46734b51dae9SMat Martineau 		} else {
46744b51dae9SMat Martineau 			BT_DBG("Expected");
46754b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
46764b51dae9SMat Martineau 		}
46774b51dae9SMat Martineau 	}
46784b51dae9SMat Martineau 
46794b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
46804b51dae9SMat Martineau 		__seq_offset(chan, chan->expected_tx_seq,
46814b51dae9SMat Martineau 			     chan->last_acked_seq)){
46824b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
46834b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
46844b51dae9SMat Martineau 	}
46854b51dae9SMat Martineau 
46864b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
46874b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
46884b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
46894b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
46904b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
46914b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
46924b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
46934b51dae9SMat Martineau 		 * request.
46944b51dae9SMat Martineau 		 *
46954b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
46964b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
46974b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
46984b51dae9SMat Martineau 		 *
46994b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
47004b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
47014b51dae9SMat Martineau 		 * causes a disconnect.
47024b51dae9SMat Martineau 		 */
47034b51dae9SMat Martineau 
47044b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
47054b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
47064b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
47074b51dae9SMat Martineau 		} else {
47084b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
47094b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
47104b51dae9SMat Martineau 		}
47114b51dae9SMat Martineau 	} else {
47124b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
47134b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
47144b51dae9SMat Martineau 	}
47154b51dae9SMat Martineau }
47164b51dae9SMat Martineau 
4717d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
4718d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
4719d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
4720d2a7ac5dSMat Martineau {
4721d2a7ac5dSMat Martineau 	int err = 0;
4722d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4723d2a7ac5dSMat Martineau 
4724d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4725d2a7ac5dSMat Martineau 	       event);
4726d2a7ac5dSMat Martineau 
4727d2a7ac5dSMat Martineau 	switch (event) {
4728d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4729d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
4730d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4731d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4732d2a7ac5dSMat Martineau 
4733d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4734d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
4735d2a7ac5dSMat Martineau 				       control->txseq);
4736d2a7ac5dSMat Martineau 				break;
4737d2a7ac5dSMat Martineau 			}
4738d2a7ac5dSMat Martineau 
4739d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
4740d2a7ac5dSMat Martineau 							   control->txseq);
4741d2a7ac5dSMat Martineau 
4742d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
4743d2a7ac5dSMat Martineau 			skb_in_use = 1;
4744d2a7ac5dSMat Martineau 
4745d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
4746d2a7ac5dSMat Martineau 			if (err)
4747d2a7ac5dSMat Martineau 				break;
4748d2a7ac5dSMat Martineau 
4749d2a7ac5dSMat Martineau 			if (control->final) {
4750d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
4751d2a7ac5dSMat Martineau 							&chan->conn_state)) {
4752d2a7ac5dSMat Martineau 					control->final = 0;
4753d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
4754d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
4755d2a7ac5dSMat Martineau 				}
4756d2a7ac5dSMat Martineau 			}
4757d2a7ac5dSMat Martineau 
4758d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
4759d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
4760d2a7ac5dSMat Martineau 			break;
4761d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4762d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4763d2a7ac5dSMat Martineau 
4764d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
4765d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
4766d2a7ac5dSMat Martineau 			 * when local busy is exited.
4767d2a7ac5dSMat Martineau 			 */
4768d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4769d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
4770d2a7ac5dSMat Martineau 				       control->txseq);
4771d2a7ac5dSMat Martineau 				break;
4772d2a7ac5dSMat Martineau 			}
4773d2a7ac5dSMat Martineau 
4774d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
4775d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
4776d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
4777d2a7ac5dSMat Martineau 			 */
4778d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4779d2a7ac5dSMat Martineau 			skb_in_use = 1;
4780d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4781d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4782d2a7ac5dSMat Martineau 
4783d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
4784d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
4785d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4786d2a7ac5dSMat Martineau 
4787d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
4788d2a7ac5dSMat Martineau 			break;
4789d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4790d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4791d2a7ac5dSMat Martineau 			break;
4792d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4793d2a7ac5dSMat Martineau 			break;
4794d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4795d2a7ac5dSMat Martineau 		default:
4796d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4797d2a7ac5dSMat Martineau 					       ECONNRESET);
4798d2a7ac5dSMat Martineau 			break;
4799d2a7ac5dSMat Martineau 		}
4800d2a7ac5dSMat Martineau 		break;
4801d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4802d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4803d2a7ac5dSMat Martineau 		if (control->final) {
4804d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4805d2a7ac5dSMat Martineau 
4806d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4807d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4808d2a7ac5dSMat Martineau 				control->final = 0;
4809d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4810d2a7ac5dSMat Martineau 			}
4811d2a7ac5dSMat Martineau 
4812d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4813d2a7ac5dSMat Martineau 		} else if (control->poll) {
4814d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
4815d2a7ac5dSMat Martineau 		} else {
4816d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4817d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4818d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4819d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4820d2a7ac5dSMat Martineau 
4821d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4822d2a7ac5dSMat Martineau 		}
4823d2a7ac5dSMat Martineau 		break;
4824d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4825d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4826d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4827d2a7ac5dSMat Martineau 		if (control && control->poll) {
4828d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4829d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
4830d2a7ac5dSMat Martineau 		}
4831d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
4832d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
4833d2a7ac5dSMat Martineau 		break;
4834d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4835d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4836d2a7ac5dSMat Martineau 		break;
4837d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4838d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4839d2a7ac5dSMat Martineau 		break;
4840d2a7ac5dSMat Martineau 	default:
4841d2a7ac5dSMat Martineau 		break;
4842d2a7ac5dSMat Martineau 	}
4843d2a7ac5dSMat Martineau 
4844d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4845d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4846d2a7ac5dSMat Martineau 		kfree_skb(skb);
4847d2a7ac5dSMat Martineau 	}
4848d2a7ac5dSMat Martineau 
4849d2a7ac5dSMat Martineau 	return err;
4850d2a7ac5dSMat Martineau }
4851d2a7ac5dSMat Martineau 
4852d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
4853d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
4854d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
4855d2a7ac5dSMat Martineau {
4856d2a7ac5dSMat Martineau 	int err = 0;
4857d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
4858d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4859d2a7ac5dSMat Martineau 
4860d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4861d2a7ac5dSMat Martineau 	       event);
4862d2a7ac5dSMat Martineau 
4863d2a7ac5dSMat Martineau 	switch (event) {
4864d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4865d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
4866d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4867d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
4868d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4869d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4870d2a7ac5dSMat Martineau 			skb_in_use = 1;
4871d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4872d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4873d2a7ac5dSMat Martineau 
4874d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
4875d2a7ac5dSMat Martineau 			break;
4876d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
4877d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
4878d2a7ac5dSMat Martineau 
4879d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4880d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4881d2a7ac5dSMat Martineau 			skb_in_use = 1;
4882d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4883d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4884d2a7ac5dSMat Martineau 
4885d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
4886d2a7ac5dSMat Martineau 			if (err)
4887d2a7ac5dSMat Martineau 				break;
4888d2a7ac5dSMat Martineau 
4889d2a7ac5dSMat Martineau 			break;
4890d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4891d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
4892d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
4893d2a7ac5dSMat Martineau 			 * the missing frames.
4894d2a7ac5dSMat Martineau 			 */
4895d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4896d2a7ac5dSMat Martineau 			skb_in_use = 1;
4897d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4898d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4899d2a7ac5dSMat Martineau 
4900d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4901d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4902d2a7ac5dSMat Martineau 			break;
4903d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
4904d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
4905d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
4906d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
4907d2a7ac5dSMat Martineau 			 * SREJ'd frames.
4908d2a7ac5dSMat Martineau 			 */
4909d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4910d2a7ac5dSMat Martineau 			skb_in_use = 1;
4911d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4912d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4913d2a7ac5dSMat Martineau 
4914d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4915d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
4916d2a7ac5dSMat Martineau 			break;
4917d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
4918d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
4919d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4920d2a7ac5dSMat Martineau 			break;
4921d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4922d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
4923d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
4924d2a7ac5dSMat Martineau 			 */
4925d2a7ac5dSMat Martineau 			break;
4926d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4927d2a7ac5dSMat Martineau 			break;
4928d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4929d2a7ac5dSMat Martineau 		default:
4930d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4931d2a7ac5dSMat Martineau 					       ECONNRESET);
4932d2a7ac5dSMat Martineau 			break;
4933d2a7ac5dSMat Martineau 		}
4934d2a7ac5dSMat Martineau 		break;
4935d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4936d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4937d2a7ac5dSMat Martineau 		if (control->final) {
4938d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4939d2a7ac5dSMat Martineau 
4940d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4941d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4942d2a7ac5dSMat Martineau 				control->final = 0;
4943d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4944d2a7ac5dSMat Martineau 			}
4945d2a7ac5dSMat Martineau 
4946d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4947d2a7ac5dSMat Martineau 		} else if (control->poll) {
4948d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4949d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4950d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
4951d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4952d2a7ac5dSMat Martineau 			}
4953d2a7ac5dSMat Martineau 
4954d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4955d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4956d2a7ac5dSMat Martineau 		} else {
4957d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4958d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4959d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4960d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4961d2a7ac5dSMat Martineau 
4962d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
4963d2a7ac5dSMat Martineau 		}
4964d2a7ac5dSMat Martineau 		break;
4965d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4966d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4967d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4968d2a7ac5dSMat Martineau 		if (control->poll) {
4969d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4970d2a7ac5dSMat Martineau 		} else {
4971d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
4972d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
4973d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
4974d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
4975d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
4976d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
4977d2a7ac5dSMat Martineau 		}
4978d2a7ac5dSMat Martineau 
4979d2a7ac5dSMat Martineau 		break;
4980d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4981d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4982d2a7ac5dSMat Martineau 		break;
4983d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4984d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4985d2a7ac5dSMat Martineau 		break;
4986d2a7ac5dSMat Martineau 	}
4987d2a7ac5dSMat Martineau 
4988d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4989d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4990d2a7ac5dSMat Martineau 		kfree_skb(skb);
4991d2a7ac5dSMat Martineau 	}
4992d2a7ac5dSMat Martineau 
4993d2a7ac5dSMat Martineau 	return err;
4994d2a7ac5dSMat Martineau }
4995d2a7ac5dSMat Martineau 
4996d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
4997d2a7ac5dSMat Martineau {
4998d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
4999d2a7ac5dSMat Martineau 	u16 unacked;
5000d2a7ac5dSMat Martineau 
5001d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
5002d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
5003d2a7ac5dSMat Martineau }
5004d2a7ac5dSMat Martineau 
5005cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5006cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
50070a708f8fSGustavo F. Padovan {
5008d2a7ac5dSMat Martineau 	int err = 0;
5009d2a7ac5dSMat Martineau 
5010d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
5011d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
5012d2a7ac5dSMat Martineau 
5013d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
5014d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
5015d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
5016d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
5017d2a7ac5dSMat Martineau 			break;
5018d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
5019d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
5020d2a7ac5dSMat Martineau 						       event);
5021d2a7ac5dSMat Martineau 			break;
5022d2a7ac5dSMat Martineau 		default:
5023d2a7ac5dSMat Martineau 			/* shut it down */
5024d2a7ac5dSMat Martineau 			break;
5025d2a7ac5dSMat Martineau 		}
5026d2a7ac5dSMat Martineau 	} else {
5027d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
5028d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
5029d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
5030d2a7ac5dSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
5031d2a7ac5dSMat Martineau 	}
5032d2a7ac5dSMat Martineau 
5033d2a7ac5dSMat Martineau 	return err;
5034cec8ab6eSMat Martineau }
5035cec8ab6eSMat Martineau 
5036cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5037cec8ab6eSMat Martineau 			   struct sk_buff *skb)
5038cec8ab6eSMat Martineau {
50394b51dae9SMat Martineau 	int err = 0;
50404b51dae9SMat Martineau 
50414b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
50424b51dae9SMat Martineau 	       chan->rx_state);
50434b51dae9SMat Martineau 
50444b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
50454b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
50464b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
50474b51dae9SMat Martineau 
50484b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
50494b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
50504b51dae9SMat Martineau 
50514b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
50524b51dae9SMat Martineau 
50534b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
50544b51dae9SMat Martineau 	} else {
50554b51dae9SMat Martineau 		if (chan->sdu) {
50564b51dae9SMat Martineau 			kfree_skb(chan->sdu);
50574b51dae9SMat Martineau 			chan->sdu = NULL;
50584b51dae9SMat Martineau 		}
50594b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
50604b51dae9SMat Martineau 		chan->sdu_len = 0;
50614b51dae9SMat Martineau 
50624b51dae9SMat Martineau 		if (skb) {
50634b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
50644b51dae9SMat Martineau 			kfree_skb(skb);
50654b51dae9SMat Martineau 		}
50664b51dae9SMat Martineau 	}
50674b51dae9SMat Martineau 
50684b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
50694b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
50704b51dae9SMat Martineau 
50714b51dae9SMat Martineau 	return err;
5072cec8ab6eSMat Martineau }
5073cec8ab6eSMat Martineau 
5074cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
5075cec8ab6eSMat Martineau {
5076cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
5077cec8ab6eSMat Martineau 	u16 len;
5078cec8ab6eSMat Martineau 	u8 event;
50790a708f8fSGustavo F. Padovan 
5080b76bbd66SMat Martineau 	__unpack_control(chan, skb);
5081b76bbd66SMat Martineau 
50820a708f8fSGustavo F. Padovan 	len = skb->len;
50830a708f8fSGustavo F. Padovan 
50840a708f8fSGustavo F. Padovan 	/*
50850a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
50860a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
5087cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
50880a708f8fSGustavo F. Padovan 	 */
508947d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
50900a708f8fSGustavo F. Padovan 		goto drop;
50910a708f8fSGustavo F. Padovan 
5092cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
509303a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
50940a708f8fSGustavo F. Padovan 
509547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
509603a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
50970a708f8fSGustavo F. Padovan 
509847d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
50998c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51000a708f8fSGustavo F. Padovan 		goto drop;
51010a708f8fSGustavo F. Padovan 	}
51020a708f8fSGustavo F. Padovan 
5103cec8ab6eSMat Martineau 	if (!control->sframe) {
5104cec8ab6eSMat Martineau 		int err;
51050a708f8fSGustavo F. Padovan 
5106cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
5107cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
5108cec8ab6eSMat Martineau 		       control->txseq);
5109836be934SAndrei Emeltchenko 
5110cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
5111cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
5112cec8ab6eSMat Martineau 		 */
5113cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
51140a708f8fSGustavo F. Padovan 			goto drop;
51150a708f8fSGustavo F. Padovan 
5116cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
5117cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
5118cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
51190a708f8fSGustavo F. Padovan 		} else {
5120cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
5121cec8ab6eSMat Martineau 		}
5122cec8ab6eSMat Martineau 
5123cec8ab6eSMat Martineau 		if (err)
5124cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
5125cec8ab6eSMat Martineau 					       ECONNRESET);
5126cec8ab6eSMat Martineau 	} else {
5127cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
5128cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5129cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5130cec8ab6eSMat Martineau 		};
5131cec8ab6eSMat Martineau 
5132cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
5133cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
5134cec8ab6eSMat Martineau 			goto drop;
5135cec8ab6eSMat Martineau 
5136cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5137cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
5138cec8ab6eSMat Martineau 		       control->super);
5139cec8ab6eSMat Martineau 
51400a708f8fSGustavo F. Padovan 		if (len != 0) {
51410a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
51428c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51430a708f8fSGustavo F. Padovan 			goto drop;
51440a708f8fSGustavo F. Padovan 		}
51450a708f8fSGustavo F. Padovan 
5146cec8ab6eSMat Martineau 		/* Validate F and P bits */
5147cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
5148cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5149cec8ab6eSMat Martineau 			goto drop;
5150cec8ab6eSMat Martineau 
5151cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
5152cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
5153cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51540a708f8fSGustavo F. Padovan 	}
51550a708f8fSGustavo F. Padovan 
51560a708f8fSGustavo F. Padovan 	return 0;
51570a708f8fSGustavo F. Padovan 
51580a708f8fSGustavo F. Padovan drop:
51590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
51600a708f8fSGustavo F. Padovan 	return 0;
51610a708f8fSGustavo F. Padovan }
51620a708f8fSGustavo F. Padovan 
516313ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
516413ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
51650a708f8fSGustavo F. Padovan {
516648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
51670a708f8fSGustavo F. Padovan 
5168baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
516948454079SGustavo F. Padovan 	if (!chan) {
517097e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
517197e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
517297e8e89dSAndrei Emeltchenko 			if (!chan) {
517397e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
517413ca56e0SAndrei Emeltchenko 				return;
517597e8e89dSAndrei Emeltchenko 			}
517697e8e89dSAndrei Emeltchenko 
517797e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
517897e8e89dSAndrei Emeltchenko 		} else {
51790a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
51806be36555SAndrei Emeltchenko 			/* Drop packet and return */
51813379013bSDan Carpenter 			kfree_skb(skb);
518213ca56e0SAndrei Emeltchenko 			return;
51830a708f8fSGustavo F. Padovan 		}
518497e8e89dSAndrei Emeltchenko 	}
51850a708f8fSGustavo F. Padovan 
518649208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
51870a708f8fSGustavo F. Padovan 
518889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
51890a708f8fSGustavo F. Padovan 		goto drop;
51900a708f8fSGustavo F. Padovan 
51910c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
51920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
51930a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
51940a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
51950a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
51960a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
51970a708f8fSGustavo F. Padovan 
51980c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
51990a708f8fSGustavo F. Padovan 			goto drop;
52000a708f8fSGustavo F. Padovan 
520180b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
52020a708f8fSGustavo F. Padovan 			goto done;
52030a708f8fSGustavo F. Padovan 		break;
52040a708f8fSGustavo F. Padovan 
52050a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
52060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
5207cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
52080a708f8fSGustavo F. Padovan 		goto done;
52090a708f8fSGustavo F. Padovan 
52100a708f8fSGustavo F. Padovan 	default:
52110c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
52120a708f8fSGustavo F. Padovan 		break;
52130a708f8fSGustavo F. Padovan 	}
52140a708f8fSGustavo F. Padovan 
52150a708f8fSGustavo F. Padovan drop:
52160a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52170a708f8fSGustavo F. Padovan 
52180a708f8fSGustavo F. Padovan done:
52196be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
52200a708f8fSGustavo F. Padovan }
52210a708f8fSGustavo F. Padovan 
522284104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
522384104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
52240a708f8fSGustavo F. Padovan {
522523691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52260a708f8fSGustavo F. Padovan 
5227c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
522823691d75SGustavo F. Padovan 	if (!chan)
52290a708f8fSGustavo F. Padovan 		goto drop;
52300a708f8fSGustavo F. Padovan 
52315b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52320a708f8fSGustavo F. Padovan 
523389bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52340a708f8fSGustavo F. Padovan 		goto drop;
52350a708f8fSGustavo F. Padovan 
5236e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52370a708f8fSGustavo F. Padovan 		goto drop;
52380a708f8fSGustavo F. Padovan 
523980b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
524084104b24SAndrei Emeltchenko 		return;
52410a708f8fSGustavo F. Padovan 
52420a708f8fSGustavo F. Padovan drop:
52430a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52440a708f8fSGustavo F. Padovan }
52450a708f8fSGustavo F. Padovan 
52466810fca7SAndrei Emeltchenko static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5247d9b88702SAndrei Emeltchenko 			      struct sk_buff *skb)
52489f69bda6SGustavo F. Padovan {
524923691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52509f69bda6SGustavo F. Padovan 
5251c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
525223691d75SGustavo F. Padovan 	if (!chan)
52539f69bda6SGustavo F. Padovan 		goto drop;
52549f69bda6SGustavo F. Padovan 
52555b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52569f69bda6SGustavo F. Padovan 
525789bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52589f69bda6SGustavo F. Padovan 		goto drop;
52599f69bda6SGustavo F. Padovan 
5260e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52619f69bda6SGustavo F. Padovan 		goto drop;
52629f69bda6SGustavo F. Padovan 
526380b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
52646810fca7SAndrei Emeltchenko 		return;
52659f69bda6SGustavo F. Padovan 
52669f69bda6SGustavo F. Padovan drop:
52679f69bda6SGustavo F. Padovan 	kfree_skb(skb);
52689f69bda6SGustavo F. Padovan }
52699f69bda6SGustavo F. Padovan 
52700a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
52710a708f8fSGustavo F. Padovan {
52720a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
52730a708f8fSGustavo F. Padovan 	u16 cid, len;
52740a708f8fSGustavo F. Padovan 	__le16 psm;
52750a708f8fSGustavo F. Padovan 
52760a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
52770a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
52780a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
52790a708f8fSGustavo F. Padovan 
52800a708f8fSGustavo F. Padovan 	if (len != skb->len) {
52810a708f8fSGustavo F. Padovan 		kfree_skb(skb);
52820a708f8fSGustavo F. Padovan 		return;
52830a708f8fSGustavo F. Padovan 	}
52840a708f8fSGustavo F. Padovan 
52850a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
52860a708f8fSGustavo F. Padovan 
52870a708f8fSGustavo F. Padovan 	switch (cid) {
52883300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
52890a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
52900a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
52910a708f8fSGustavo F. Padovan 		break;
52920a708f8fSGustavo F. Padovan 
52930a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
5294097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
52950181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
52960a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
52970a708f8fSGustavo F. Padovan 		break;
52980a708f8fSGustavo F. Padovan 
52999f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
53009f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
53019f69bda6SGustavo F. Padovan 		break;
53029f69bda6SGustavo F. Padovan 
5303b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
5304b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
5305b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
5306b501d6a1SAnderson Briglia 		break;
5307b501d6a1SAnderson Briglia 
53080a708f8fSGustavo F. Padovan 	default:
53090a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
53100a708f8fSGustavo F. Padovan 		break;
53110a708f8fSGustavo F. Padovan 	}
53120a708f8fSGustavo F. Padovan }
53130a708f8fSGustavo F. Padovan 
53140a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
53150a708f8fSGustavo F. Padovan 
5316686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
53170a708f8fSGustavo F. Padovan {
53180a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
531923691d75SGustavo F. Padovan 	struct l2cap_chan *c;
53200a708f8fSGustavo F. Padovan 
53210a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
53220a708f8fSGustavo F. Padovan 
53230a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
532423691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
532523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
532623691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
53274343478fSGustavo F. Padovan 
532889bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
53290a708f8fSGustavo F. Padovan 			continue;
53300a708f8fSGustavo F. Padovan 
53310a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
53320a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
533343bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53340a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
53350a708f8fSGustavo F. Padovan 			exact++;
53360a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
53370a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
533843bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53390a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
53400a708f8fSGustavo F. Padovan 		}
53410a708f8fSGustavo F. Padovan 	}
534223691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
53430a708f8fSGustavo F. Padovan 
53440a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
53450a708f8fSGustavo F. Padovan }
53460a708f8fSGustavo F. Padovan 
53479e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
53480a708f8fSGustavo F. Padovan {
53490a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
53500a708f8fSGustavo F. Padovan 
53510a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
53520a708f8fSGustavo F. Padovan 
53530a708f8fSGustavo F. Padovan 	if (!status) {
53540a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
53550a708f8fSGustavo F. Padovan 		if (conn)
53560a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
53570a708f8fSGustavo F. Padovan 	} else
5358e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
53590a708f8fSGustavo F. Padovan 
53600a708f8fSGustavo F. Padovan }
53610a708f8fSGustavo F. Padovan 
5362686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
53630a708f8fSGustavo F. Padovan {
53640a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
53650a708f8fSGustavo F. Padovan 
53660a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
53670a708f8fSGustavo F. Padovan 
5368686ebf28SUlisses Furquim 	if (!conn)
53699f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
53700a708f8fSGustavo F. Padovan 	return conn->disc_reason;
53710a708f8fSGustavo F. Padovan }
53720a708f8fSGustavo F. Padovan 
53739e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
53740a708f8fSGustavo F. Padovan {
53750a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
53760a708f8fSGustavo F. Padovan 
5377e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
53780a708f8fSGustavo F. Padovan }
53790a708f8fSGustavo F. Padovan 
53804343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
53810a708f8fSGustavo F. Padovan {
5382715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
53830a708f8fSGustavo F. Padovan 		return;
53840a708f8fSGustavo F. Padovan 
53850a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
53864343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
5387ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
53884343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
53890f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
53900a708f8fSGustavo F. Padovan 	} else {
53914343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
5392c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
53930a708f8fSGustavo F. Padovan 	}
53940a708f8fSGustavo F. Padovan }
53950a708f8fSGustavo F. Padovan 
5396686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
53970a708f8fSGustavo F. Padovan {
53980a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
539948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
54000a708f8fSGustavo F. Padovan 
54010a708f8fSGustavo F. Padovan 	if (!conn)
54020a708f8fSGustavo F. Padovan 		return 0;
54030a708f8fSGustavo F. Padovan 
540489d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
54050a708f8fSGustavo F. Padovan 
5406160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
540735d4adccSHemant Gupta 		if (!status && encrypt)
5408160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
540917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
5410160dc6acSVinicius Costa Gomes 	}
5411160dc6acSVinicius Costa Gomes 
54123df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
54130a708f8fSGustavo F. Padovan 
54143df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
54156be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
54160a708f8fSGustavo F. Padovan 
541789d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
541889d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
5419f1cb9af5SVinicius Costa Gomes 
542078eb2f98SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
542178eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
542278eb2f98SAndrei Emeltchenko 			continue;
542378eb2f98SAndrei Emeltchenko 		}
542478eb2f98SAndrei Emeltchenko 
5425f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
5426f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
5427f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
5428cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
5429f1cb9af5SVinicius Costa Gomes 			}
5430f1cb9af5SVinicius Costa Gomes 
54316be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
5432f1cb9af5SVinicius Costa Gomes 			continue;
5433f1cb9af5SVinicius Costa Gomes 		}
5434f1cb9af5SVinicius Costa Gomes 
5435c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
54366be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54370a708f8fSGustavo F. Padovan 			continue;
54380a708f8fSGustavo F. Padovan 		}
54390a708f8fSGustavo F. Padovan 
544089bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
544189bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
5442a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
5443a7d7723aSGustavo Padovan 
5444c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
5445a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
5446a7d7723aSGustavo Padovan 
54474343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
54486be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54490a708f8fSGustavo F. Padovan 			continue;
54500a708f8fSGustavo F. Padovan 		}
54510a708f8fSGustavo F. Padovan 
545289bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
54530a708f8fSGustavo F. Padovan 			if (!status) {
54549b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
54550a708f8fSGustavo F. Padovan 			} else {
5456ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
54570a708f8fSGustavo F. Padovan 			}
545889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
54596be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
54600a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5461df3c3931SJohan Hedberg 			__u16 res, stat;
54620a708f8fSGustavo F. Padovan 
54636be36555SAndrei Emeltchenko 			lock_sock(sk);
54646be36555SAndrei Emeltchenko 
54650a708f8fSGustavo F. Padovan 			if (!status) {
5466c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
5467c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
5468df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
5469df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
5470df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
547105e9a2f6SIlia Kolomisnky 					if (parent)
5472df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
5473df3c3931SJohan Hedberg 				} else {
54740e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
5475df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
5476df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
5477df3c3931SJohan Hedberg 				}
54780a708f8fSGustavo F. Padovan 			} else {
54790e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
5480ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
5481df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
5482df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
54830a708f8fSGustavo F. Padovan 			}
54840a708f8fSGustavo F. Padovan 
54856be36555SAndrei Emeltchenko 			release_sock(sk);
54866be36555SAndrei Emeltchenko 
5487fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5488fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5489df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
5490df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
5491fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5492fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
54932d369359SMat Martineau 
54942d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
54952d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
54962d369359SMat Martineau 				char buf[128];
54972d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
54982d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
54992d369359SMat Martineau 					       L2CAP_CONF_REQ,
55002d369359SMat Martineau 					       l2cap_build_conf_req(chan, buf),
55012d369359SMat Martineau 					       buf);
55022d369359SMat Martineau 				chan->num_conf_req++;
55032d369359SMat Martineau 			}
55040a708f8fSGustavo F. Padovan 		}
55050a708f8fSGustavo F. Padovan 
55066be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
55070a708f8fSGustavo F. Padovan 	}
55080a708f8fSGustavo F. Padovan 
55093df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
55100a708f8fSGustavo F. Padovan 
55110a708f8fSGustavo F. Padovan 	return 0;
55120a708f8fSGustavo F. Padovan }
55130a708f8fSGustavo F. Padovan 
5514686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
55150a708f8fSGustavo F. Padovan {
55160a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
55170a708f8fSGustavo F. Padovan 
55180a708f8fSGustavo F. Padovan 	if (!conn)
55190a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
55200a708f8fSGustavo F. Padovan 
55210a708f8fSGustavo F. Padovan 	if (!conn)
55220a708f8fSGustavo F. Padovan 		goto drop;
55230a708f8fSGustavo F. Padovan 
55240a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
55250a708f8fSGustavo F. Padovan 
55260a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
55270a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
55280a708f8fSGustavo F. Padovan 		int len;
55290a708f8fSGustavo F. Padovan 
55300a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
55310a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
55320a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55330a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55340a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55350a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55360a708f8fSGustavo F. Padovan 		}
55370a708f8fSGustavo F. Padovan 
55380a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
55390a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
55400a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
55410a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55420a708f8fSGustavo F. Padovan 			goto drop;
55430a708f8fSGustavo F. Padovan 		}
55440a708f8fSGustavo F. Padovan 
55450a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
55460a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
55470a708f8fSGustavo F. Padovan 
55480a708f8fSGustavo F. Padovan 		if (len == skb->len) {
55490a708f8fSGustavo F. Padovan 			/* Complete frame received */
55500a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
55510a708f8fSGustavo F. Padovan 			return 0;
55520a708f8fSGustavo F. Padovan 		}
55530a708f8fSGustavo F. Padovan 
55540a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
55550a708f8fSGustavo F. Padovan 
55560a708f8fSGustavo F. Padovan 		if (skb->len > len) {
55570a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
55580a708f8fSGustavo F. Padovan 				skb->len, len);
55590a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55600a708f8fSGustavo F. Padovan 			goto drop;
55610a708f8fSGustavo F. Padovan 		}
55620a708f8fSGustavo F. Padovan 
55630a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
55640a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
55650a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
55660a708f8fSGustavo F. Padovan 			goto drop;
55670a708f8fSGustavo F. Padovan 
55680a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55690a708f8fSGustavo F. Padovan 								skb->len);
55700a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
55710a708f8fSGustavo F. Padovan 	} else {
55720a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
55730a708f8fSGustavo F. Padovan 
55740a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
55750a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
55760a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55770a708f8fSGustavo F. Padovan 			goto drop;
55780a708f8fSGustavo F. Padovan 		}
55790a708f8fSGustavo F. Padovan 
55800a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
55810a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
55820a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
55830a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55840a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55850a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55860a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55870a708f8fSGustavo F. Padovan 			goto drop;
55880a708f8fSGustavo F. Padovan 		}
55890a708f8fSGustavo F. Padovan 
55900a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55910a708f8fSGustavo F. Padovan 								skb->len);
55920a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
55930a708f8fSGustavo F. Padovan 
55940a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
55950a708f8fSGustavo F. Padovan 			/* Complete frame received */
55960a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
55970a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55980a708f8fSGustavo F. Padovan 		}
55990a708f8fSGustavo F. Padovan 	}
56000a708f8fSGustavo F. Padovan 
56010a708f8fSGustavo F. Padovan drop:
56020a708f8fSGustavo F. Padovan 	kfree_skb(skb);
56030a708f8fSGustavo F. Padovan 	return 0;
56040a708f8fSGustavo F. Padovan }
56050a708f8fSGustavo F. Padovan 
56060a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
56070a708f8fSGustavo F. Padovan {
560823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
56090a708f8fSGustavo F. Padovan 
5610333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
56110a708f8fSGustavo F. Padovan 
561223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
561323691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
56140a708f8fSGustavo F. Padovan 
5615903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
56160a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
56170a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
561889bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
561923691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
562023691d75SGustavo F. Padovan 					c->sec_level, c->mode);
56210a708f8fSGustavo F. Padovan 	}
56220a708f8fSGustavo F. Padovan 
5623333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
56240a708f8fSGustavo F. Padovan 
56250a708f8fSGustavo F. Padovan 	return 0;
56260a708f8fSGustavo F. Padovan }
56270a708f8fSGustavo F. Padovan 
56280a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
56290a708f8fSGustavo F. Padovan {
56300a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
56310a708f8fSGustavo F. Padovan }
56320a708f8fSGustavo F. Padovan 
56330a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
56340a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
56350a708f8fSGustavo F. Padovan 	.read		= seq_read,
56360a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
56370a708f8fSGustavo F. Padovan 	.release	= single_release,
56380a708f8fSGustavo F. Padovan };
56390a708f8fSGustavo F. Padovan 
56400a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
56410a708f8fSGustavo F. Padovan 
564264274518SGustavo F. Padovan int __init l2cap_init(void)
56430a708f8fSGustavo F. Padovan {
56440a708f8fSGustavo F. Padovan 	int err;
56450a708f8fSGustavo F. Padovan 
5646bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
56470a708f8fSGustavo F. Padovan 	if (err < 0)
56480a708f8fSGustavo F. Padovan 		return err;
56490a708f8fSGustavo F. Padovan 
56500a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
56510a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
56520a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
56530a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
56540a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
56550a708f8fSGustavo F. Padovan 	}
56560a708f8fSGustavo F. Padovan 
56570a708f8fSGustavo F. Padovan 	return 0;
56580a708f8fSGustavo F. Padovan }
56590a708f8fSGustavo F. Padovan 
566064274518SGustavo F. Padovan void l2cap_exit(void)
56610a708f8fSGustavo F. Padovan {
56620a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5663bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
56640a708f8fSGustavo F. Padovan }
56650a708f8fSGustavo F. Padovan 
56660a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
56670a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5668