xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 59e54bd1)
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>
400a708f8fSGustavo F. Padovan 
41d1de6d46SMat Martineau bool disable_ertm;
420a708f8fSGustavo F. Padovan 
430a708f8fSGustavo F. Padovan static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
4450a147cdSMat Martineau static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, };
450a708f8fSGustavo F. Padovan 
46b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
47b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
480a708f8fSGustavo F. Padovan 
490a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
500a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data);
514519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
524519de9aSGustavo F. Padovan 								void *data);
53710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
544519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn,
554519de9aSGustavo F. Padovan 				   struct l2cap_chan *chan, int err);
560a708f8fSGustavo F. Padovan 
57d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
58608bcc6dSMat Martineau 		    struct sk_buff_head *skbs, u8 event);
59608bcc6dSMat Martineau 
600a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
6171ba0e56SGustavo F. Padovan 
62baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
630a708f8fSGustavo F. Padovan {
643df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
65baa7e1faSGustavo F. Padovan 
663df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
673df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
683df91ea2SAndrei Emeltchenko 			return c;
690a708f8fSGustavo F. Padovan 	}
703df91ea2SAndrei Emeltchenko 	return NULL;
71baa7e1faSGustavo F. Padovan }
720a708f8fSGustavo F. Padovan 
73baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
740a708f8fSGustavo F. Padovan {
753df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
76baa7e1faSGustavo F. Padovan 
773df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
783df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
793df91ea2SAndrei Emeltchenko 			return c;
800a708f8fSGustavo F. Padovan 	}
813df91ea2SAndrei Emeltchenko 	return NULL;
82baa7e1faSGustavo F. Padovan }
830a708f8fSGustavo F. Padovan 
840a708f8fSGustavo F. Padovan /* Find channel with given SCID.
85ef191adeSMat Martineau  * Returns locked channel. */
86baa7e1faSGustavo F. Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)
870a708f8fSGustavo F. Padovan {
8848454079SGustavo F. Padovan 	struct l2cap_chan *c;
89baa7e1faSGustavo F. Padovan 
903df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
91baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
92ef191adeSMat Martineau 	if (c)
93ef191adeSMat Martineau 		l2cap_chan_lock(c);
943df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
953df91ea2SAndrei Emeltchenko 
9648454079SGustavo F. Padovan 	return c;
970a708f8fSGustavo F. Padovan }
980a708f8fSGustavo F. Padovan 
99baa7e1faSGustavo F. Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)
1000a708f8fSGustavo F. Padovan {
1013df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
102baa7e1faSGustavo F. Padovan 
1033df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1043df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1053df91ea2SAndrei Emeltchenko 			return c;
1060a708f8fSGustavo F. Padovan 	}
1073df91ea2SAndrei Emeltchenko 	return NULL;
108baa7e1faSGustavo F. Padovan }
1090a708f8fSGustavo F. Padovan 
11023691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1119e4425ffSGustavo F. Padovan {
11223691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1139e4425ffSGustavo F. Padovan 
11423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
11523691d75SGustavo F. Padovan 		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
11623691d75SGustavo F. Padovan 			return c;
1179e4425ffSGustavo F. Padovan 	}
118250938cbSSzymon Janc 	return NULL;
119250938cbSSzymon Janc }
1209e4425ffSGustavo F. Padovan 
1219e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1229e4425ffSGustavo F. Padovan {
12373b2ec18SGustavo F. Padovan 	int err;
12473b2ec18SGustavo F. Padovan 
125333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1269e4425ffSGustavo F. Padovan 
12723691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
12873b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
12973b2ec18SGustavo F. Padovan 		goto done;
1309e4425ffSGustavo F. Padovan 	}
1319e4425ffSGustavo F. Padovan 
13273b2ec18SGustavo F. Padovan 	if (psm) {
1339e4425ffSGustavo F. Padovan 		chan->psm = psm;
1349e4425ffSGustavo F. Padovan 		chan->sport = psm;
13573b2ec18SGustavo F. Padovan 		err = 0;
13673b2ec18SGustavo F. Padovan 	} else {
13773b2ec18SGustavo F. Padovan 		u16 p;
1389e4425ffSGustavo F. Padovan 
13973b2ec18SGustavo F. Padovan 		err = -EINVAL;
14073b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
14123691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
14273b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
14373b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
14473b2ec18SGustavo F. Padovan 				err = 0;
14573b2ec18SGustavo F. Padovan 				break;
14673b2ec18SGustavo F. Padovan 			}
14773b2ec18SGustavo F. Padovan 	}
14873b2ec18SGustavo F. Padovan 
14973b2ec18SGustavo F. Padovan done:
150333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
15173b2ec18SGustavo F. Padovan 	return err;
1529e4425ffSGustavo F. Padovan }
1539e4425ffSGustavo F. Padovan 
1549e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
1559e4425ffSGustavo F. Padovan {
156333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1579e4425ffSGustavo F. Padovan 
1589e4425ffSGustavo F. Padovan 	chan->scid = scid;
1599e4425ffSGustavo F. Padovan 
160333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
1619e4425ffSGustavo F. Padovan 
1629e4425ffSGustavo F. Padovan 	return 0;
1639e4425ffSGustavo F. Padovan }
1649e4425ffSGustavo F. Padovan 
165baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
1660a708f8fSGustavo F. Padovan {
1670a708f8fSGustavo F. Padovan 	u16 cid = L2CAP_CID_DYN_START;
1680a708f8fSGustavo F. Padovan 
1690a708f8fSGustavo F. Padovan 	for (; cid < L2CAP_CID_DYN_END; cid++) {
170baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
1710a708f8fSGustavo F. Padovan 			return cid;
1720a708f8fSGustavo F. Padovan 	}
1730a708f8fSGustavo F. Padovan 
1740a708f8fSGustavo F. Padovan 	return 0;
1750a708f8fSGustavo F. Padovan }
1760a708f8fSGustavo F. Padovan 
1770e587be7SAndrei Emeltchenko static void __l2cap_state_change(struct l2cap_chan *chan, int state)
17889bc500eSGustavo F. Padovan {
17942d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
180badaaa00SGustavo F. Padovan 						state_to_string(state));
181badaaa00SGustavo F. Padovan 
18289bc500eSGustavo F. Padovan 	chan->state = state;
18389bc500eSGustavo F. Padovan 	chan->ops->state_change(chan->data, state);
18489bc500eSGustavo F. Padovan }
18589bc500eSGustavo F. Padovan 
1860e587be7SAndrei Emeltchenko static void l2cap_state_change(struct l2cap_chan *chan, int state)
1870e587be7SAndrei Emeltchenko {
1880e587be7SAndrei Emeltchenko 	struct sock *sk = chan->sk;
1890e587be7SAndrei Emeltchenko 
1900e587be7SAndrei Emeltchenko 	lock_sock(sk);
1910e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, state);
1920e587be7SAndrei Emeltchenko 	release_sock(sk);
1930e587be7SAndrei Emeltchenko }
1940e587be7SAndrei Emeltchenko 
1952e0052e4SAndrei Emeltchenko static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
1962e0052e4SAndrei Emeltchenko {
1972e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
1982e0052e4SAndrei Emeltchenko 
1992e0052e4SAndrei Emeltchenko 	sk->sk_err = err;
2002e0052e4SAndrei Emeltchenko }
2012e0052e4SAndrei Emeltchenko 
2022e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2032e0052e4SAndrei Emeltchenko {
2042e0052e4SAndrei Emeltchenko 	struct sock *sk = chan->sk;
2052e0052e4SAndrei Emeltchenko 
2062e0052e4SAndrei Emeltchenko 	lock_sock(sk);
2072e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
2082e0052e4SAndrei Emeltchenko 	release_sock(sk);
2092e0052e4SAndrei Emeltchenko }
2102e0052e4SAndrei Emeltchenko 
2114239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2124239d16fSMat Martineau {
2134239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2144239d16fSMat Martineau 	    chan->retrans_timeout) {
2154239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2164239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2174239d16fSMat Martineau 	}
2184239d16fSMat Martineau }
2194239d16fSMat Martineau 
2204239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2214239d16fSMat Martineau {
2224239d16fSMat Martineau 	__clear_retrans_timer(chan);
2234239d16fSMat Martineau 	if (chan->monitor_timeout) {
2244239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2254239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2264239d16fSMat Martineau 	}
2274239d16fSMat Martineau }
2284239d16fSMat Martineau 
229608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
230608bcc6dSMat Martineau 					       u16 seq)
231608bcc6dSMat Martineau {
232608bcc6dSMat Martineau 	struct sk_buff *skb;
233608bcc6dSMat Martineau 
234608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
235608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
236608bcc6dSMat Martineau 			return skb;
237608bcc6dSMat Martineau 	}
238608bcc6dSMat Martineau 
239608bcc6dSMat Martineau 	return NULL;
240608bcc6dSMat Martineau }
241608bcc6dSMat Martineau 
2423c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2433c588192SMat Martineau 
2443c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2453c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2463c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2473c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2483c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2493c588192SMat Martineau  * and removed from the head in constant time, without further memory
2503c588192SMat Martineau  * allocs or frees.
2513c588192SMat Martineau  */
2523c588192SMat Martineau 
2533c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2543c588192SMat Martineau {
2553c588192SMat Martineau 	size_t alloc_size, i;
2563c588192SMat Martineau 
2573c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2583c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
2593c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
2603c588192SMat Martineau 	 */
2613c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
2623c588192SMat Martineau 
2633c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
2643c588192SMat Martineau 	if (!seq_list->list)
2653c588192SMat Martineau 		return -ENOMEM;
2663c588192SMat Martineau 
2673c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
2683c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
2693c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
2703c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
2713c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
2723c588192SMat Martineau 
2733c588192SMat Martineau 	return 0;
2743c588192SMat Martineau }
2753c588192SMat Martineau 
2763c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
2773c588192SMat Martineau {
2783c588192SMat Martineau 	kfree(seq_list->list);
2793c588192SMat Martineau }
2803c588192SMat Martineau 
2813c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
2823c588192SMat Martineau 					   u16 seq)
2833c588192SMat Martineau {
2843c588192SMat Martineau 	/* Constant-time check for list membership */
2853c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
2863c588192SMat Martineau }
2873c588192SMat Martineau 
2883c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
2893c588192SMat Martineau {
2903c588192SMat Martineau 	u16 mask = seq_list->mask;
2913c588192SMat Martineau 
2923c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
2933c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
2943c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
2953c588192SMat Martineau 	} else if (seq_list->head == seq) {
2963c588192SMat Martineau 		/* Head can be removed in constant time */
2973c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
2983c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
2993c588192SMat Martineau 
3003c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3013c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3023c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3033c588192SMat Martineau 		}
3043c588192SMat Martineau 	} else {
3053c588192SMat Martineau 		/* Walk the list to find the sequence number */
3063c588192SMat Martineau 		u16 prev = seq_list->head;
3073c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3083c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3093c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3103c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3113c588192SMat Martineau 		}
3123c588192SMat Martineau 
3133c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3143c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3153c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3163c588192SMat Martineau 		if (seq_list->tail == seq)
3173c588192SMat Martineau 			seq_list->tail = prev;
3183c588192SMat Martineau 	}
3193c588192SMat Martineau 	return seq;
3203c588192SMat Martineau }
3213c588192SMat Martineau 
3223c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3233c588192SMat Martineau {
3243c588192SMat Martineau 	/* Remove the head in constant time */
3253c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3263c588192SMat Martineau }
3273c588192SMat Martineau 
3283c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3293c588192SMat Martineau {
3303c588192SMat Martineau 	u16 i;
331f522ae36SGustavo Padovan 
332f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
333f522ae36SGustavo Padovan 		return;
334f522ae36SGustavo Padovan 
3353c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3363c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3373c588192SMat Martineau 
3383c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3393c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau }
3413c588192SMat Martineau 
3423c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3433c588192SMat Martineau {
3443c588192SMat Martineau 	u16 mask = seq_list->mask;
3453c588192SMat Martineau 
3463c588192SMat Martineau 	/* All appends happen in constant time */
3473c588192SMat Martineau 
348f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
349f522ae36SGustavo Padovan 		return;
350f522ae36SGustavo Padovan 
3513c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3523c588192SMat Martineau 		seq_list->head = seq;
3533c588192SMat Martineau 	else
3543c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3553c588192SMat Martineau 
3563c588192SMat Martineau 	seq_list->tail = seq;
3573c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3583c588192SMat Martineau }
3593c588192SMat Martineau 
360721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
361ab07801dSGustavo F. Padovan {
362721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
363721c4181SGustavo F. Padovan 							chan_timer.work);
3643df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
365ab07801dSGustavo F. Padovan 	int reason;
366ab07801dSGustavo F. Padovan 
367e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
368ab07801dSGustavo F. Padovan 
3693df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3706be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
371ab07801dSGustavo F. Padovan 
37289bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
373ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
37489bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
375ab07801dSGustavo F. Padovan 					chan->sec_level != BT_SECURITY_SDP)
376ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
377ab07801dSGustavo F. Padovan 	else
378ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
379ab07801dSGustavo F. Padovan 
3800f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
381ab07801dSGustavo F. Padovan 
3826be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
383ab07801dSGustavo F. Padovan 
384ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
3853df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
3863df91ea2SAndrei Emeltchenko 
387371fd835SUlisses Furquim 	l2cap_chan_put(chan);
388ab07801dSGustavo F. Padovan }
389ab07801dSGustavo F. Padovan 
390eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
3910a708f8fSGustavo F. Padovan {
39248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
3930a708f8fSGustavo F. Padovan 
39448454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
39548454079SGustavo F. Padovan 	if (!chan)
39648454079SGustavo F. Padovan 		return NULL;
3970a708f8fSGustavo F. Padovan 
398c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
399c03b355eSAndrei Emeltchenko 
400333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
40123691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
402333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
40323691d75SGustavo F. Padovan 
404721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
405ab07801dSGustavo F. Padovan 
40689bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
40789bc500eSGustavo F. Padovan 
40871ba0e56SGustavo F. Padovan 	atomic_set(&chan->refcnt, 1);
40971ba0e56SGustavo F. Padovan 
4102827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4112827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4122827011fSMat Martineau 
413eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
414abc545b8SSzymon Janc 
41548454079SGustavo F. Padovan 	return chan;
4160a708f8fSGustavo F. Padovan }
4170a708f8fSGustavo F. Padovan 
41823691d75SGustavo F. Padovan void l2cap_chan_destroy(struct l2cap_chan *chan)
4196ff5abbfSGustavo F. Padovan {
420333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
42123691d75SGustavo F. Padovan 	list_del(&chan->global_l);
422333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
42323691d75SGustavo F. Padovan 
424371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4256ff5abbfSGustavo F. Padovan }
4266ff5abbfSGustavo F. Padovan 
427bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
428bd4b1653SAndrei Emeltchenko {
429bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
430bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
431bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
432bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
433bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
434bd4b1653SAndrei Emeltchenko 
435bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
436bd4b1653SAndrei Emeltchenko }
437bd4b1653SAndrei Emeltchenko 
43814a28491SAndrei Emeltchenko static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
4390a708f8fSGustavo F. Padovan {
4400a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
441097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
4420a708f8fSGustavo F. Padovan 
4439f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
4440a708f8fSGustavo F. Padovan 
4458c1d787bSGustavo F. Padovan 	chan->conn = conn;
4460a708f8fSGustavo F. Padovan 
4475491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
4485491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
449b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
450b62f328bSVille Tervo 			/* LE connection */
4510c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_LE_DEFAULT_MTU;
452fe4128e0SGustavo F. Padovan 			chan->scid = L2CAP_CID_LE_DATA;
453fe4128e0SGustavo F. Padovan 			chan->dcid = L2CAP_CID_LE_DATA;
454b62f328bSVille Tervo 		} else {
4550a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
456fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
4570c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
458b62f328bSVille Tervo 		}
4595491120eSAndrei Emeltchenko 		break;
4605491120eSAndrei Emeltchenko 
4615491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
4620a708f8fSGustavo F. Padovan 		/* Connectionless socket */
463fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
464fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
4650c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4665491120eSAndrei Emeltchenko 		break;
4675491120eSAndrei Emeltchenko 
4685491120eSAndrei Emeltchenko 	default:
4690a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
470fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
471fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
4720c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
4730a708f8fSGustavo F. Padovan 	}
4740a708f8fSGustavo F. Padovan 
4758f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
4768f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
4778f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
4788f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
4798f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
4808f7975b1SAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_DEFAULT_FLUSH_TO;
4818f7975b1SAndrei Emeltchenko 
482371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
483baa7e1faSGustavo F. Padovan 
4843df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
485643162a8SAndrei Emeltchenko }
486643162a8SAndrei Emeltchenko 
48714a28491SAndrei Emeltchenko static void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
488643162a8SAndrei Emeltchenko {
489643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
490643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
4913df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4920a708f8fSGustavo F. Padovan }
4930a708f8fSGustavo F. Padovan 
4944519de9aSGustavo F. Padovan static void l2cap_chan_del(struct l2cap_chan *chan, int err)
4950a708f8fSGustavo F. Padovan {
49648454079SGustavo F. Padovan 	struct sock *sk = chan->sk;
4978c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4980a708f8fSGustavo F. Padovan 	struct sock *parent = bt_sk(sk)->parent;
4990a708f8fSGustavo F. Padovan 
500c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5010a708f8fSGustavo F. Padovan 
50249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5030a708f8fSGustavo F. Padovan 
5040a708f8fSGustavo F. Padovan 	if (conn) {
505baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5063df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5073d57dc68SGustavo F. Padovan 
508371fd835SUlisses Furquim 		l2cap_chan_put(chan);
509baa7e1faSGustavo F. Padovan 
5108c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5110a708f8fSGustavo F. Padovan 		hci_conn_put(conn->hcon);
5120a708f8fSGustavo F. Padovan 	}
5130a708f8fSGustavo F. Padovan 
5146be36555SAndrei Emeltchenko 	lock_sock(sk);
5156be36555SAndrei Emeltchenko 
5160e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CLOSED);
5170a708f8fSGustavo F. Padovan 	sock_set_flag(sk, SOCK_ZAPPED);
5180a708f8fSGustavo F. Padovan 
5190a708f8fSGustavo F. Padovan 	if (err)
5202e0052e4SAndrei Emeltchenko 		__l2cap_chan_set_err(chan, err);
5210a708f8fSGustavo F. Padovan 
5220a708f8fSGustavo F. Padovan 	if (parent) {
5230a708f8fSGustavo F. Padovan 		bt_accept_unlink(sk);
5240a708f8fSGustavo F. Padovan 		parent->sk_data_ready(parent, 0);
5250a708f8fSGustavo F. Padovan 	} else
5260a708f8fSGustavo F. Padovan 		sk->sk_state_change(sk);
5270a708f8fSGustavo F. Padovan 
5286be36555SAndrei Emeltchenko 	release_sock(sk);
5296be36555SAndrei Emeltchenko 
5302827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
5316ff5abbfSGustavo F. Padovan 		return;
5322ead70b8SGustavo F. Padovan 
533ee556f66SGustavo Padovan 	switch(chan->mode) {
534ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
535ee556f66SGustavo Padovan 		break;
5360a708f8fSGustavo F. Padovan 
537ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
5381a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
5391a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
5401a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
5410a708f8fSGustavo F. Padovan 
542f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
5430a708f8fSGustavo F. Padovan 
5443c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
5453c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
546ee556f66SGustavo Padovan 
547ee556f66SGustavo Padovan 		/* fall through */
548ee556f66SGustavo Padovan 
549ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
550ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
551ee556f66SGustavo Padovan 		break;
5520a708f8fSGustavo F. Padovan 	}
553ee556f66SGustavo Padovan 
554ee556f66SGustavo Padovan 	return;
5550a708f8fSGustavo F. Padovan }
5560a708f8fSGustavo F. Padovan 
5574519de9aSGustavo F. Padovan static void l2cap_chan_cleanup_listen(struct sock *parent)
5584519de9aSGustavo F. Padovan {
5594519de9aSGustavo F. Padovan 	struct sock *sk;
5604519de9aSGustavo F. Padovan 
5614519de9aSGustavo F. Padovan 	BT_DBG("parent %p", parent);
5624519de9aSGustavo F. Padovan 
5634519de9aSGustavo F. Padovan 	/* Close not yet accepted channels */
5640f852724SGustavo F. Padovan 	while ((sk = bt_accept_dequeue(parent, NULL))) {
565ba3bd0eeSGustavo F. Padovan 		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
5663df91ea2SAndrei Emeltchenko 
5676be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
568c9b66675SGustavo F. Padovan 		__clear_chan_timer(chan);
569ba3bd0eeSGustavo F. Padovan 		l2cap_chan_close(chan, ECONNRESET);
5706be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
5713df91ea2SAndrei Emeltchenko 
572ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
5730f852724SGustavo F. Padovan 	}
5744519de9aSGustavo F. Padovan }
5754519de9aSGustavo F. Padovan 
5760f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
5774519de9aSGustavo F. Padovan {
5784519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5794519de9aSGustavo F. Padovan 	struct sock *sk = chan->sk;
5804519de9aSGustavo F. Padovan 
581e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s sk %p", chan,
582e05dcc32SAndrei Emeltchenko 					state_to_string(chan->state), sk);
5834519de9aSGustavo F. Padovan 
58489bc500eSGustavo F. Padovan 	switch (chan->state) {
5854519de9aSGustavo F. Padovan 	case BT_LISTEN:
5866be36555SAndrei Emeltchenko 		lock_sock(sk);
5874519de9aSGustavo F. Padovan 		l2cap_chan_cleanup_listen(sk);
58889bc500eSGustavo F. Padovan 
5890e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CLOSED);
59089bc500eSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
5916be36555SAndrei Emeltchenko 		release_sock(sk);
5924519de9aSGustavo F. Padovan 		break;
5934519de9aSGustavo F. Padovan 
5944519de9aSGustavo F. Padovan 	case BT_CONNECTED:
5954519de9aSGustavo F. Padovan 	case BT_CONFIG:
596715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
5974519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
598c9b66675SGustavo F. Padovan 			__set_chan_timer(chan, sk->sk_sndtimeo);
5994519de9aSGustavo F. Padovan 			l2cap_send_disconn_req(conn, chan, reason);
6004519de9aSGustavo F. Padovan 		} else
6014519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
6024519de9aSGustavo F. Padovan 		break;
6034519de9aSGustavo F. Padovan 
6044519de9aSGustavo F. Padovan 	case BT_CONNECT2:
605715ec005SGustavo F. Padovan 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
6064519de9aSGustavo F. Padovan 					conn->hcon->type == ACL_LINK) {
6074519de9aSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
6084519de9aSGustavo F. Padovan 			__u16 result;
6094519de9aSGustavo F. Padovan 
610c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
6114519de9aSGustavo F. Padovan 				result = L2CAP_CR_SEC_BLOCK;
6124519de9aSGustavo F. Padovan 			else
6134519de9aSGustavo F. Padovan 				result = L2CAP_CR_BAD_PSM;
61489bc500eSGustavo F. Padovan 			l2cap_state_change(chan, BT_DISCONN);
6154519de9aSGustavo F. Padovan 
6164519de9aSGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
6174519de9aSGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
6184519de9aSGustavo F. Padovan 			rsp.result = cpu_to_le16(result);
6194519de9aSGustavo F. Padovan 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
6204519de9aSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
6214519de9aSGustavo F. Padovan 							sizeof(rsp), &rsp);
6224519de9aSGustavo F. Padovan 		}
6234519de9aSGustavo F. Padovan 
6244519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6254519de9aSGustavo F. Padovan 		break;
6264519de9aSGustavo F. Padovan 
6274519de9aSGustavo F. Padovan 	case BT_CONNECT:
6284519de9aSGustavo F. Padovan 	case BT_DISCONN:
6294519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
6304519de9aSGustavo F. Padovan 		break;
6314519de9aSGustavo F. Padovan 
6324519de9aSGustavo F. Padovan 	default:
6336be36555SAndrei Emeltchenko 		lock_sock(sk);
6344519de9aSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
6356be36555SAndrei Emeltchenko 		release_sock(sk);
6364519de9aSGustavo F. Padovan 		break;
6374519de9aSGustavo F. Padovan 	}
6384519de9aSGustavo F. Padovan }
6394519de9aSGustavo F. Padovan 
6404343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
6410a708f8fSGustavo F. Padovan {
642715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_RAW) {
6434343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6440a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6450a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
6460a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6470a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
6480a708f8fSGustavo F. Padovan 		default:
6490a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6500a708f8fSGustavo F. Padovan 		}
651fe4128e0SGustavo F. Padovan 	} else if (chan->psm == cpu_to_le16(0x0001)) {
6524343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_LOW)
6534343478fSGustavo F. Padovan 			chan->sec_level = BT_SECURITY_SDP;
6540a708f8fSGustavo F. Padovan 
6554343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_HIGH)
6560a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING_MITM;
6570a708f8fSGustavo F. Padovan 		else
6580a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6590a708f8fSGustavo F. Padovan 	} else {
6604343478fSGustavo F. Padovan 		switch (chan->sec_level) {
6610a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
6620a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
6630a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
6640a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
6650a708f8fSGustavo F. Padovan 		default:
6660a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
6670a708f8fSGustavo F. Padovan 		}
6680a708f8fSGustavo F. Padovan 	}
6690a708f8fSGustavo F. Padovan }
6700a708f8fSGustavo F. Padovan 
6710a708f8fSGustavo F. Padovan /* Service level security */
672d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
6730a708f8fSGustavo F. Padovan {
6748c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6750a708f8fSGustavo F. Padovan 	__u8 auth_type;
6760a708f8fSGustavo F. Padovan 
6774343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
6780a708f8fSGustavo F. Padovan 
6794343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
6800a708f8fSGustavo F. Padovan }
6810a708f8fSGustavo F. Padovan 
682b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
6830a708f8fSGustavo F. Padovan {
6840a708f8fSGustavo F. Padovan 	u8 id;
6850a708f8fSGustavo F. Padovan 
6860a708f8fSGustavo F. Padovan 	/* Get next available identificator.
6870a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
6880a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
6890a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
6900a708f8fSGustavo F. Padovan 	 */
6910a708f8fSGustavo F. Padovan 
692333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
6930a708f8fSGustavo F. Padovan 
6940a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
6950a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
6960a708f8fSGustavo F. Padovan 
6970a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
6980a708f8fSGustavo F. Padovan 
699333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
7000a708f8fSGustavo F. Padovan 
7010a708f8fSGustavo F. Padovan 	return id;
7020a708f8fSGustavo F. Padovan }
7030a708f8fSGustavo F. Padovan 
7044519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
7050a708f8fSGustavo F. Padovan {
7060a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
7070a708f8fSGustavo F. Padovan 	u8 flags;
7080a708f8fSGustavo F. Padovan 
7090a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
7100a708f8fSGustavo F. Padovan 
7110a708f8fSGustavo F. Padovan 	if (!skb)
7120a708f8fSGustavo F. Padovan 		return;
7130a708f8fSGustavo F. Padovan 
7140a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
7150a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
7160a708f8fSGustavo F. Padovan 	else
7170a708f8fSGustavo F. Padovan 		flags = ACL_START;
7180a708f8fSGustavo F. Padovan 
71914b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
7205e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
72114b12d0bSJaikumar Ganesh 
72273d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
7230a708f8fSGustavo F. Padovan }
7240a708f8fSGustavo F. Padovan 
72573d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
72673d80debSLuiz Augusto von Dentz {
72773d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
72873d80debSLuiz Augusto von Dentz 	u16 flags;
72973d80debSLuiz Augusto von Dentz 
73073d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
73173d80debSLuiz Augusto von Dentz 							skb->priority);
73273d80debSLuiz Augusto von Dentz 
73373d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
73473d80debSLuiz Augusto von Dentz 					lmp_no_flush_capable(hcon->hdev))
73573d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
73673d80debSLuiz Augusto von Dentz 	else
73773d80debSLuiz Augusto von Dentz 		flags = ACL_START;
73873d80debSLuiz Augusto von Dentz 
73973d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
74073d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
7410a708f8fSGustavo F. Padovan }
7420a708f8fSGustavo F. Padovan 
743b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
744b5c6aaedSMat Martineau {
745b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
746b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
747b5c6aaedSMat Martineau 
748b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
749b5c6aaedSMat Martineau 		/* S-Frame */
750b5c6aaedSMat Martineau 		control->sframe = 1;
751b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
752b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
753b5c6aaedSMat Martineau 
754b5c6aaedSMat Martineau 		control->sar = 0;
755b5c6aaedSMat Martineau 		control->txseq = 0;
756b5c6aaedSMat Martineau 	} else {
757b5c6aaedSMat Martineau 		/* I-Frame */
758b5c6aaedSMat Martineau 		control->sframe = 0;
759b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
760b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
761b5c6aaedSMat Martineau 
762b5c6aaedSMat Martineau 		control->poll = 0;
763b5c6aaedSMat Martineau 		control->super = 0;
764b5c6aaedSMat Martineau 	}
765b5c6aaedSMat Martineau }
766b5c6aaedSMat Martineau 
767b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
768b5c6aaedSMat Martineau {
769b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
770b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
771b5c6aaedSMat Martineau 
772b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
773b5c6aaedSMat Martineau 		/* S-Frame */
774b5c6aaedSMat Martineau 		control->sframe = 1;
775b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
776b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
777b5c6aaedSMat Martineau 
778b5c6aaedSMat Martineau 		control->sar = 0;
779b5c6aaedSMat Martineau 		control->txseq = 0;
780b5c6aaedSMat Martineau 	} else {
781b5c6aaedSMat Martineau 		/* I-Frame */
782b5c6aaedSMat Martineau 		control->sframe = 0;
783b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
784b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
785b5c6aaedSMat Martineau 
786b5c6aaedSMat Martineau 		control->poll = 0;
787b5c6aaedSMat Martineau 		control->super = 0;
788b5c6aaedSMat Martineau 	}
789b5c6aaedSMat Martineau }
790b5c6aaedSMat Martineau 
791b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
792b5c6aaedSMat Martineau 				    struct sk_buff *skb)
793b5c6aaedSMat Martineau {
794b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
795b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
796b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
797cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
798b5c6aaedSMat Martineau 	} else {
799b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
800b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
801cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
802b5c6aaedSMat Martineau 	}
803b5c6aaedSMat Martineau }
804b5c6aaedSMat Martineau 
805b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
806b5c6aaedSMat Martineau {
807b5c6aaedSMat Martineau 	u32 packed;
808b5c6aaedSMat Martineau 
809b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
810b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
811b5c6aaedSMat Martineau 
812b5c6aaedSMat Martineau 	if (control->sframe) {
813b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
814b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
815b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
816b5c6aaedSMat Martineau 	} else {
817b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
818b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
819b5c6aaedSMat Martineau 	}
820b5c6aaedSMat Martineau 
821b5c6aaedSMat Martineau 	return packed;
822b5c6aaedSMat Martineau }
823b5c6aaedSMat Martineau 
824b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
825b5c6aaedSMat Martineau {
826b5c6aaedSMat Martineau 	u16 packed;
827b5c6aaedSMat Martineau 
828b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
829b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
830b5c6aaedSMat Martineau 
831b5c6aaedSMat Martineau 	if (control->sframe) {
832b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
833b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
834b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
835b5c6aaedSMat Martineau 	} else {
836b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
837b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
838b5c6aaedSMat Martineau 	}
839b5c6aaedSMat Martineau 
840b5c6aaedSMat Martineau 	return packed;
841b5c6aaedSMat Martineau }
842b5c6aaedSMat Martineau 
843b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
844b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
845b5c6aaedSMat Martineau 				  struct sk_buff *skb)
846b5c6aaedSMat Martineau {
847b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
848b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
849b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
850b5c6aaedSMat Martineau 	} else {
851b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
852b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
853b5c6aaedSMat Martineau 	}
854b5c6aaedSMat Martineau }
855b5c6aaedSMat Martineau 
856a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
857a67d7f6fSMat Martineau 					       u32 control)
8580a708f8fSGustavo F. Padovan {
8590a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
8600a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
861a67d7f6fSMat Martineau 	int hlen;
8620a708f8fSGustavo F. Padovan 
863e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
864e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
865e4ca6d98SAndrei Emeltchenko 	else
866e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
8670a708f8fSGustavo F. Padovan 
8680a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
86903a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
8700a708f8fSGustavo F. Padovan 
871a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
8720a708f8fSGustavo F. Padovan 
8730a708f8fSGustavo F. Padovan 	if (!skb)
874a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
8750a708f8fSGustavo F. Padovan 
8760a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
8770a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
878fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
87988843ab0SAndrei Emeltchenko 
880a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
881a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
882a67d7f6fSMat Martineau 	else
883a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
8840a708f8fSGustavo F. Padovan 
88547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
886a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
88703a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
8880a708f8fSGustavo F. Padovan 	}
8890a708f8fSGustavo F. Padovan 
89073d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
891a67d7f6fSMat Martineau 	return skb;
892a67d7f6fSMat Martineau }
893a67d7f6fSMat Martineau 
894a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
895a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
896a67d7f6fSMat Martineau {
897a67d7f6fSMat Martineau 	struct sk_buff *skb;
898a67d7f6fSMat Martineau 	u32 control_field;
899a67d7f6fSMat Martineau 
900a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
901a67d7f6fSMat Martineau 
902a67d7f6fSMat Martineau 	if (!control->sframe)
903a67d7f6fSMat Martineau 		return;
904a67d7f6fSMat Martineau 
905a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
906a67d7f6fSMat Martineau 	    !control->poll)
907a67d7f6fSMat Martineau 		control->final = 1;
908a67d7f6fSMat Martineau 
909a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
910a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
911a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
912a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
913a67d7f6fSMat Martineau 
914a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
915a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
916a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
917a67d7f6fSMat Martineau 	}
918a67d7f6fSMat Martineau 
919a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
920a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
921a67d7f6fSMat Martineau 
922a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
923a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
924a67d7f6fSMat Martineau 	else
925a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
926a67d7f6fSMat Martineau 
927a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
928a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
92973d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
9300a708f8fSGustavo F. Padovan }
9310a708f8fSGustavo F. Padovan 
932c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
9330a708f8fSGustavo F. Padovan {
934c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
9350a708f8fSGustavo F. Padovan 
936c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
937c9e3d5e0SMat Martineau 
938c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
939c9e3d5e0SMat Martineau 	control.sframe = 1;
940c9e3d5e0SMat Martineau 	control.poll = poll;
941c9e3d5e0SMat Martineau 
942c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
943c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
944c9e3d5e0SMat Martineau 	else
945c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
946c9e3d5e0SMat Martineau 
947c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
948c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
9490a708f8fSGustavo F. Padovan }
9500a708f8fSGustavo F. Padovan 
951b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
9520a708f8fSGustavo F. Padovan {
953c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
9540a708f8fSGustavo F. Padovan }
9550a708f8fSGustavo F. Padovan 
9569b27f350SAndrei Emeltchenko static void l2cap_send_conn_req(struct l2cap_chan *chan)
9579b27f350SAndrei Emeltchenko {
9589b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
9599b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
9609b27f350SAndrei Emeltchenko 
9619b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
9629b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
9639b27f350SAndrei Emeltchenko 
9649b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
9659b27f350SAndrei Emeltchenko 
9669b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
9679b27f350SAndrei Emeltchenko 
9689b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
9699b27f350SAndrei Emeltchenko }
9709b27f350SAndrei Emeltchenko 
9719f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
9729f0caeb1SVinicius Costa Gomes {
9739f0caeb1SVinicius Costa Gomes 	struct sock *sk = chan->sk;
9749f0caeb1SVinicius Costa Gomes 	struct sock *parent;
9759f0caeb1SVinicius Costa Gomes 
9769f0caeb1SVinicius Costa Gomes 	lock_sock(sk);
9779f0caeb1SVinicius Costa Gomes 
9789f0caeb1SVinicius Costa Gomes 	parent = bt_sk(sk)->parent;
9799f0caeb1SVinicius Costa Gomes 
9809f0caeb1SVinicius Costa Gomes 	BT_DBG("sk %p, parent %p", sk, parent);
9819f0caeb1SVinicius Costa Gomes 
9822827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
9839f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
9849f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
9859f0caeb1SVinicius Costa Gomes 
9869f0caeb1SVinicius Costa Gomes 	__l2cap_state_change(chan, BT_CONNECTED);
9879f0caeb1SVinicius Costa Gomes 	sk->sk_state_change(sk);
9889f0caeb1SVinicius Costa Gomes 
9899f0caeb1SVinicius Costa Gomes 	if (parent)
9909f0caeb1SVinicius Costa Gomes 		parent->sk_data_ready(parent, 0);
9919f0caeb1SVinicius Costa Gomes 
9929f0caeb1SVinicius Costa Gomes 	release_sock(sk);
9939f0caeb1SVinicius Costa Gomes }
9949f0caeb1SVinicius Costa Gomes 
995fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
9960a708f8fSGustavo F. Padovan {
9978c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9980a708f8fSGustavo F. Padovan 
9999f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
10009f0caeb1SVinicius Costa Gomes 		l2cap_chan_ready(chan);
10019f0caeb1SVinicius Costa Gomes 		return;
10029f0caeb1SVinicius Costa Gomes 	}
10039f0caeb1SVinicius Costa Gomes 
10040a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
10050a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
10060a708f8fSGustavo F. Padovan 			return;
10070a708f8fSGustavo F. Padovan 
1008d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
10099b27f350SAndrei Emeltchenko 				__l2cap_no_conn_pending(chan))
10109b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
10110a708f8fSGustavo F. Padovan 	} else {
10120a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
10130a708f8fSGustavo F. Padovan 		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
10140a708f8fSGustavo F. Padovan 
10150a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
10160a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
10170a708f8fSGustavo F. Padovan 
1018ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
10190a708f8fSGustavo F. Padovan 
10200a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
10210a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
10220a708f8fSGustavo F. Padovan 	}
10230a708f8fSGustavo F. Padovan }
10240a708f8fSGustavo F. Padovan 
10250a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
10260a708f8fSGustavo F. Padovan {
10270a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
10280a708f8fSGustavo F. Padovan 	if (!disable_ertm)
10290a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
10300a708f8fSGustavo F. Padovan 
10310a708f8fSGustavo F. Padovan 	switch (mode) {
10320a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
10330a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
10340a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
10350a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
10360a708f8fSGustavo F. Padovan 	default:
10370a708f8fSGustavo F. Padovan 		return 0x00;
10380a708f8fSGustavo F. Padovan 	}
10390a708f8fSGustavo F. Padovan }
10400a708f8fSGustavo F. Padovan 
10414519de9aSGustavo F. Padovan static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
10420a708f8fSGustavo F. Padovan {
10436be36555SAndrei Emeltchenko 	struct sock *sk = chan->sk;
10440a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
10450a708f8fSGustavo F. Padovan 
10460a708f8fSGustavo F. Padovan 	if (!conn)
10470a708f8fSGustavo F. Padovan 		return;
10480a708f8fSGustavo F. Padovan 
10490c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_ERTM) {
10501a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
10511a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
10521a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
10530a708f8fSGustavo F. Padovan 	}
10540a708f8fSGustavo F. Padovan 
1055fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1056fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
10570a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn),
10580a708f8fSGustavo F. Padovan 			L2CAP_DISCONN_REQ, sizeof(req), &req);
10590a708f8fSGustavo F. Padovan 
10606be36555SAndrei Emeltchenko 	lock_sock(sk);
10610e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_DISCONN);
10622e0052e4SAndrei Emeltchenko 	__l2cap_chan_set_err(chan, err);
10636be36555SAndrei Emeltchenko 	release_sock(sk);
10640a708f8fSGustavo F. Padovan }
10650a708f8fSGustavo F. Padovan 
10660a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
10670a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
10680a708f8fSGustavo F. Padovan {
10693df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
10700a708f8fSGustavo F. Padovan 
10710a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
10720a708f8fSGustavo F. Padovan 
10733df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
10740a708f8fSGustavo F. Padovan 
10753df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
107648454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
1077baa7e1faSGustavo F. Padovan 
10786be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
10790a708f8fSGustavo F. Padovan 
1080715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
10816be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
10820a708f8fSGustavo F. Padovan 			continue;
10830a708f8fSGustavo F. Padovan 		}
10840a708f8fSGustavo F. Padovan 
108589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1086d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1087b4450035SGustavo F. Padovan 					!__l2cap_no_conn_pending(chan)) {
10886be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10890a708f8fSGustavo F. Padovan 				continue;
10900a708f8fSGustavo F. Padovan 			}
10910a708f8fSGustavo F. Padovan 
1092c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1093c1360a1cSGustavo F. Padovan 					&& test_bit(CONF_STATE2_DEVICE,
1094c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
10950f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
10966be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
10970a708f8fSGustavo F. Padovan 				continue;
10980a708f8fSGustavo F. Padovan 			}
10990a708f8fSGustavo F. Padovan 
11009b27f350SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
11010a708f8fSGustavo F. Padovan 
110289bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
11030a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
11040a708f8fSGustavo F. Padovan 			char buf[128];
1105fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1106fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
11070a708f8fSGustavo F. Padovan 
1108d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
11096be36555SAndrei Emeltchenko 				lock_sock(sk);
1110c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
1111c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
11120a708f8fSGustavo F. Padovan 					struct sock *parent = bt_sk(sk)->parent;
11130a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11140a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
111505e9a2f6SIlia Kolomisnky 					if (parent)
11160a708f8fSGustavo F. Padovan 						parent->sk_data_ready(parent, 0);
11170a708f8fSGustavo F. Padovan 
11180a708f8fSGustavo F. Padovan 				} else {
11190e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
11200a708f8fSGustavo F. Padovan 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
11210a708f8fSGustavo F. Padovan 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
11220a708f8fSGustavo F. Padovan 				}
11236be36555SAndrei Emeltchenko 				release_sock(sk);
11240a708f8fSGustavo F. Padovan 			} else {
11250a708f8fSGustavo F. Padovan 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
11260a708f8fSGustavo F. Padovan 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
11270a708f8fSGustavo F. Padovan 			}
11280a708f8fSGustavo F. Padovan 
1129fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1130fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
11310a708f8fSGustavo F. Padovan 
1132c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
11330a708f8fSGustavo F. Padovan 					rsp.result != L2CAP_CR_SUCCESS) {
11346be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
11350a708f8fSGustavo F. Padovan 				continue;
11360a708f8fSGustavo F. Padovan 			}
11370a708f8fSGustavo F. Padovan 
1138c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
11390a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
114073ffa904SGustavo F. Padovan 						l2cap_build_conf_req(chan, buf), buf);
114173ffa904SGustavo F. Padovan 			chan->num_conf_req++;
11420a708f8fSGustavo F. Padovan 		}
11430a708f8fSGustavo F. Padovan 
11446be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
11450a708f8fSGustavo F. Padovan 	}
11460a708f8fSGustavo F. Padovan 
11473df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
11480a708f8fSGustavo F. Padovan }
11490a708f8fSGustavo F. Padovan 
1150c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1151b62f328bSVille Tervo  * Returns closest match, locked.
1152b62f328bSVille Tervo  */
1153d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1154c2287681SIdo Yariv 						    bdaddr_t *src,
1155c2287681SIdo Yariv 						    bdaddr_t *dst)
1156b62f328bSVille Tervo {
115723691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1158b62f328bSVille Tervo 
115923691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1160b62f328bSVille Tervo 
116123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
116223691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1163fe4128e0SGustavo F. Padovan 
116489bc500eSGustavo F. Padovan 		if (state && c->state != state)
1165b62f328bSVille Tervo 			continue;
1166b62f328bSVille Tervo 
116723691d75SGustavo F. Padovan 		if (c->scid == cid) {
1168c2287681SIdo Yariv 			int src_match, dst_match;
1169c2287681SIdo Yariv 			int src_any, dst_any;
1170c2287681SIdo Yariv 
1171b62f328bSVille Tervo 			/* Exact match. */
1172c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1173c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1174c2287681SIdo Yariv 			if (src_match && dst_match) {
117523691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
117623691d75SGustavo F. Padovan 				return c;
117723691d75SGustavo F. Padovan 			}
1178b62f328bSVille Tervo 
1179b62f328bSVille Tervo 			/* Closest match */
1180c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1181c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1182c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1183c2287681SIdo Yariv 			    (src_any && dst_any))
118423691d75SGustavo F. Padovan 				c1 = c;
1185b62f328bSVille Tervo 		}
1186b62f328bSVille Tervo 	}
1187280f294fSGustavo F. Padovan 
118823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1189b62f328bSVille Tervo 
119023691d75SGustavo F. Padovan 	return c1;
1191b62f328bSVille Tervo }
1192b62f328bSVille Tervo 
1193b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1194b62f328bSVille Tervo {
1195c916fbe4SGustavo F. Padovan 	struct sock *parent, *sk;
119623691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1197b62f328bSVille Tervo 
1198b62f328bSVille Tervo 	BT_DBG("");
1199b62f328bSVille Tervo 
1200b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
120123691d75SGustavo F. Padovan 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
1202c2287681SIdo Yariv 					  conn->src, conn->dst);
120323691d75SGustavo F. Padovan 	if (!pchan)
1204b62f328bSVille Tervo 		return;
1205b62f328bSVille Tervo 
120623691d75SGustavo F. Padovan 	parent = pchan->sk;
120723691d75SGustavo F. Padovan 
1208aa2ac881SGustavo F. Padovan 	lock_sock(parent);
120962f3a2cfSGustavo F. Padovan 
1210b62f328bSVille Tervo 	/* Check for backlog size */
1211b62f328bSVille Tervo 	if (sk_acceptq_is_full(parent)) {
1212b62f328bSVille Tervo 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
1213b62f328bSVille Tervo 		goto clean;
1214b62f328bSVille Tervo 	}
1215b62f328bSVille Tervo 
121680808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
121780808e43SGustavo F. Padovan 	if (!chan)
1218b62f328bSVille Tervo 		goto clean;
1219b62f328bSVille Tervo 
122080808e43SGustavo F. Padovan 	sk = chan->sk;
12215d41ce1dSGustavo F. Padovan 
1222b62f328bSVille Tervo 	hci_conn_hold(conn->hcon);
1223b62f328bSVille Tervo 
1224b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->src, conn->src);
1225b62f328bSVille Tervo 	bacpy(&bt_sk(sk)->dst, conn->dst);
1226b62f328bSVille Tervo 
1227d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
1228d1010240SGustavo F. Padovan 
12293d57dc68SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
123048454079SGustavo F. Padovan 
1231c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
1232b62f328bSVille Tervo 
12330e587be7SAndrei Emeltchenko 	__l2cap_state_change(chan, BT_CONNECTED);
1234b62f328bSVille Tervo 	parent->sk_data_ready(parent, 0);
1235b62f328bSVille Tervo 
1236b62f328bSVille Tervo clean:
1237aa2ac881SGustavo F. Padovan 	release_sock(parent);
1238b62f328bSVille Tervo }
1239b62f328bSVille Tervo 
12400a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
12410a708f8fSGustavo F. Padovan {
124248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12430a708f8fSGustavo F. Padovan 
12440a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12450a708f8fSGustavo F. Padovan 
1246b62f328bSVille Tervo 	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
1247b62f328bSVille Tervo 		l2cap_le_conn_ready(conn);
1248b62f328bSVille Tervo 
1249160dc6acSVinicius Costa Gomes 	if (conn->hcon->out && conn->hcon->type == LE_LINK)
1250160dc6acSVinicius Costa Gomes 		smp_conn_security(conn, conn->hcon->pending_sec_level);
1251160dc6acSVinicius Costa Gomes 
12523df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12530a708f8fSGustavo F. Padovan 
12543df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1255baa7e1faSGustavo F. Padovan 
12566be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
12570a708f8fSGustavo F. Padovan 
125863128451SVinicius Costa Gomes 		if (conn->hcon->type == LE_LINK) {
1259b501d6a1SAnderson Briglia 			if (smp_conn_security(conn, chan->sec_level))
1260cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
1261acd7d370SVille Tervo 
126263128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
12636be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
1264c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
12656be36555SAndrei Emeltchenko 			lock_sock(sk);
12660e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECTED);
12670a708f8fSGustavo F. Padovan 			sk->sk_state_change(sk);
12686be36555SAndrei Emeltchenko 			release_sock(sk);
1269b501d6a1SAnderson Briglia 
127089bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT)
1271fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
12720a708f8fSGustavo F. Padovan 
12736be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
12740a708f8fSGustavo F. Padovan 	}
12750a708f8fSGustavo F. Padovan 
12763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12770a708f8fSGustavo F. Padovan }
12780a708f8fSGustavo F. Padovan 
12790a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
12800a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
12810a708f8fSGustavo F. Padovan {
128248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
12830a708f8fSGustavo F. Padovan 
12840a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
12850a708f8fSGustavo F. Padovan 
12863df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
12870a708f8fSGustavo F. Padovan 
12883df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1289ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
12902e0052e4SAndrei Emeltchenko 			__l2cap_chan_set_err(chan, err);
12910a708f8fSGustavo F. Padovan 	}
12920a708f8fSGustavo F. Padovan 
12933df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
12940a708f8fSGustavo F. Padovan }
12950a708f8fSGustavo F. Padovan 
1296f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
12970a708f8fSGustavo F. Padovan {
1298f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1299030013d8SGustavo F. Padovan 							info_timer.work);
13000a708f8fSGustavo F. Padovan 
13010a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
13020a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
13030a708f8fSGustavo F. Padovan 
13040a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
13050a708f8fSGustavo F. Padovan }
13060a708f8fSGustavo F. Padovan 
13075d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
13085d3de7dfSVinicius Costa Gomes {
13095d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
13105d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
13115d3de7dfSVinicius Costa Gomes 
13125d3de7dfSVinicius Costa Gomes 	if (!conn)
13135d3de7dfSVinicius Costa Gomes 		return;
13145d3de7dfSVinicius Costa Gomes 
13155d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
13165d3de7dfSVinicius Costa Gomes 
13175d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
13185d3de7dfSVinicius Costa Gomes 
13193df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13203df91ea2SAndrei Emeltchenko 
13215d3de7dfSVinicius Costa Gomes 	/* Kill channels */
13225d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
132361d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
13246be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13256be36555SAndrei Emeltchenko 
13265d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
13276be36555SAndrei Emeltchenko 
13286be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
13296be36555SAndrei Emeltchenko 
13305d3de7dfSVinicius Costa Gomes 		chan->ops->close(chan->data);
133161d6ef3eSMat Martineau 		l2cap_chan_put(chan);
13325d3de7dfSVinicius Costa Gomes 	}
13335d3de7dfSVinicius Costa Gomes 
13343df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
13353df91ea2SAndrei Emeltchenko 
133673d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
133773d80debSLuiz Augusto von Dentz 
13385d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1339127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
13405d3de7dfSVinicius Costa Gomes 
134151a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1342127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
13438aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1344d26a2345SVinicius Costa Gomes 	}
13455d3de7dfSVinicius Costa Gomes 
13465d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
13475d3de7dfSVinicius Costa Gomes 	kfree(conn);
13485d3de7dfSVinicius Costa Gomes }
13495d3de7dfSVinicius Costa Gomes 
13506c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
13515d3de7dfSVinicius Costa Gomes {
13526c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
13536c9d42a1SGustavo F. Padovan 						security_timer.work);
13545d3de7dfSVinicius Costa Gomes 
13555d3de7dfSVinicius Costa Gomes 	l2cap_conn_del(conn->hcon, ETIMEDOUT);
13565d3de7dfSVinicius Costa Gomes }
13575d3de7dfSVinicius Costa Gomes 
13580a708f8fSGustavo F. Padovan static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
13590a708f8fSGustavo F. Padovan {
13600a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
136173d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
13620a708f8fSGustavo F. Padovan 
13630a708f8fSGustavo F. Padovan 	if (conn || status)
13640a708f8fSGustavo F. Padovan 		return conn;
13650a708f8fSGustavo F. Padovan 
136673d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
136773d80debSLuiz Augusto von Dentz 	if (!hchan)
13680a708f8fSGustavo F. Padovan 		return NULL;
13690a708f8fSGustavo F. Padovan 
137073d80debSLuiz Augusto von Dentz 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
137173d80debSLuiz Augusto von Dentz 	if (!conn) {
137273d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
137373d80debSLuiz Augusto von Dentz 		return NULL;
137473d80debSLuiz Augusto von Dentz 	}
137573d80debSLuiz Augusto von Dentz 
13760a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
13770a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
137873d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
13790a708f8fSGustavo F. Padovan 
138073d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
13810a708f8fSGustavo F. Padovan 
1382acd7d370SVille Tervo 	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
1383acd7d370SVille Tervo 		conn->mtu = hcon->hdev->le_mtu;
1384acd7d370SVille Tervo 	else
13850a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1386acd7d370SVille Tervo 
13870a708f8fSGustavo F. Padovan 	conn->src = &hcon->hdev->bdaddr;
13880a708f8fSGustavo F. Padovan 	conn->dst = &hcon->dst;
13890a708f8fSGustavo F. Padovan 
13900a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
13910a708f8fSGustavo F. Padovan 
13920a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
13933df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1394baa7e1faSGustavo F. Padovan 
1395baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
13960a708f8fSGustavo F. Padovan 
13975d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
13986c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
13995d3de7dfSVinicius Costa Gomes 	else
1400030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
14010a708f8fSGustavo F. Padovan 
14029f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
14030a708f8fSGustavo F. Padovan 
14040a708f8fSGustavo F. Padovan 	return conn;
14050a708f8fSGustavo F. Padovan }
14060a708f8fSGustavo F. Padovan 
14070a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
14080a708f8fSGustavo F. Padovan 
1409c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
14100a708f8fSGustavo F. Padovan  * Returns closest match.
14110a708f8fSGustavo F. Padovan  */
1412c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1413c2287681SIdo Yariv 						   bdaddr_t *src,
1414c2287681SIdo Yariv 						   bdaddr_t *dst)
14150a708f8fSGustavo F. Padovan {
141623691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
14170a708f8fSGustavo F. Padovan 
141823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
14190a708f8fSGustavo F. Padovan 
142023691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
142123691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
1422fe4128e0SGustavo F. Padovan 
142389bc500eSGustavo F. Padovan 		if (state && c->state != state)
14240a708f8fSGustavo F. Padovan 			continue;
14250a708f8fSGustavo F. Padovan 
142623691d75SGustavo F. Padovan 		if (c->psm == psm) {
1427c2287681SIdo Yariv 			int src_match, dst_match;
1428c2287681SIdo Yariv 			int src_any, dst_any;
1429c2287681SIdo Yariv 
14300a708f8fSGustavo F. Padovan 			/* Exact match. */
1431c2287681SIdo Yariv 			src_match = !bacmp(&bt_sk(sk)->src, src);
1432c2287681SIdo Yariv 			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
1433c2287681SIdo Yariv 			if (src_match && dst_match) {
1434a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
143523691d75SGustavo F. Padovan 				return c;
143623691d75SGustavo F. Padovan 			}
14370a708f8fSGustavo F. Padovan 
14380a708f8fSGustavo F. Padovan 			/* Closest match */
1439c2287681SIdo Yariv 			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
1440c2287681SIdo Yariv 			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
1441c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1442c2287681SIdo Yariv 			    (src_any && dst_any))
144323691d75SGustavo F. Padovan 				c1 = c;
14440a708f8fSGustavo F. Padovan 		}
14450a708f8fSGustavo F. Padovan 	}
14460a708f8fSGustavo F. Padovan 
144723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
14480a708f8fSGustavo F. Padovan 
144923691d75SGustavo F. Padovan 	return c1;
14500a708f8fSGustavo F. Padovan }
14510a708f8fSGustavo F. Padovan 
14528e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
14538e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
14540a708f8fSGustavo F. Padovan {
14555d41ce1dSGustavo F. Padovan 	struct sock *sk = chan->sk;
14560a708f8fSGustavo F. Padovan 	bdaddr_t *src = &bt_sk(sk)->src;
14570a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
14580a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
14590a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
14600a708f8fSGustavo F. Padovan 	__u8 auth_type;
14610a708f8fSGustavo F. Padovan 	int err;
14620a708f8fSGustavo F. Padovan 
14638e9f9892SAndre Guedes 	BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst),
14648e9f9892SAndre Guedes 	       dst_type, __le16_to_cpu(chan->psm));
14650a708f8fSGustavo F. Padovan 
14660a708f8fSGustavo F. Padovan 	hdev = hci_get_route(dst, src);
14670a708f8fSGustavo F. Padovan 	if (!hdev)
14680a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
14690a708f8fSGustavo F. Padovan 
147009fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
14710a708f8fSGustavo F. Padovan 
14726be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
147303a00194SGustavo F. Padovan 
147403a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
147503a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
147603a00194SGustavo F. Padovan 					chan->chan_type != L2CAP_CHAN_RAW) {
147703a00194SGustavo F. Padovan 		err = -EINVAL;
147803a00194SGustavo F. Padovan 		goto done;
147903a00194SGustavo F. Padovan 	}
148003a00194SGustavo F. Padovan 
148103a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
148203a00194SGustavo F. Padovan 		err = -EINVAL;
148303a00194SGustavo F. Padovan 		goto done;
148403a00194SGustavo F. Padovan 	}
148503a00194SGustavo F. Padovan 
148603a00194SGustavo F. Padovan 	switch (chan->mode) {
148703a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
148803a00194SGustavo F. Padovan 		break;
148903a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
149003a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
149103a00194SGustavo F. Padovan 		if (!disable_ertm)
149203a00194SGustavo F. Padovan 			break;
149303a00194SGustavo F. Padovan 		/* fall through */
149403a00194SGustavo F. Padovan 	default:
149503a00194SGustavo F. Padovan 		err = -ENOTSUPP;
149603a00194SGustavo F. Padovan 		goto done;
149703a00194SGustavo F. Padovan 	}
149803a00194SGustavo F. Padovan 
14996be36555SAndrei Emeltchenko 	lock_sock(sk);
15006be36555SAndrei Emeltchenko 
150103a00194SGustavo F. Padovan 	switch (sk->sk_state) {
150203a00194SGustavo F. Padovan 	case BT_CONNECT:
150303a00194SGustavo F. Padovan 	case BT_CONNECT2:
150403a00194SGustavo F. Padovan 	case BT_CONFIG:
150503a00194SGustavo F. Padovan 		/* Already connecting */
150603a00194SGustavo F. Padovan 		err = 0;
15076be36555SAndrei Emeltchenko 		release_sock(sk);
150803a00194SGustavo F. Padovan 		goto done;
150903a00194SGustavo F. Padovan 
151003a00194SGustavo F. Padovan 	case BT_CONNECTED:
151103a00194SGustavo F. Padovan 		/* Already connected */
151203a00194SGustavo F. Padovan 		err = -EISCONN;
15136be36555SAndrei Emeltchenko 		release_sock(sk);
151403a00194SGustavo F. Padovan 		goto done;
151503a00194SGustavo F. Padovan 
151603a00194SGustavo F. Padovan 	case BT_OPEN:
151703a00194SGustavo F. Padovan 	case BT_BOUND:
151803a00194SGustavo F. Padovan 		/* Can connect */
151903a00194SGustavo F. Padovan 		break;
152003a00194SGustavo F. Padovan 
152103a00194SGustavo F. Padovan 	default:
152203a00194SGustavo F. Padovan 		err = -EBADFD;
15236be36555SAndrei Emeltchenko 		release_sock(sk);
152403a00194SGustavo F. Padovan 		goto done;
152503a00194SGustavo F. Padovan 	}
152603a00194SGustavo F. Padovan 
152703a00194SGustavo F. Padovan 	/* Set destination address and psm */
15289219b2a0SGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, dst);
15296be36555SAndrei Emeltchenko 
15306be36555SAndrei Emeltchenko 	release_sock(sk);
15316be36555SAndrei Emeltchenko 
153203a00194SGustavo F. Padovan 	chan->psm = psm;
153303a00194SGustavo F. Padovan 	chan->dcid = cid;
15340a708f8fSGustavo F. Padovan 
15354343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
15360a708f8fSGustavo F. Padovan 
1537fe4128e0SGustavo F. Padovan 	if (chan->dcid == L2CAP_CID_LE_DATA)
15388e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
15394343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1540acd7d370SVille Tervo 	else
15418e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
15424343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1543acd7d370SVille Tervo 
154430e76272SVille Tervo 	if (IS_ERR(hcon)) {
154530e76272SVille Tervo 		err = PTR_ERR(hcon);
15460a708f8fSGustavo F. Padovan 		goto done;
154730e76272SVille Tervo 	}
15480a708f8fSGustavo F. Padovan 
15490a708f8fSGustavo F. Padovan 	conn = l2cap_conn_add(hcon, 0);
15500a708f8fSGustavo F. Padovan 	if (!conn) {
15510a708f8fSGustavo F. Padovan 		hci_conn_put(hcon);
155230e76272SVille Tervo 		err = -ENOMEM;
15530a708f8fSGustavo F. Padovan 		goto done;
15540a708f8fSGustavo F. Padovan 	}
15550a708f8fSGustavo F. Padovan 
15569f0caeb1SVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
15579f0caeb1SVinicius Costa Gomes 		err = 0;
15589f0caeb1SVinicius Costa Gomes 
15599f0caeb1SVinicius Costa Gomes 		if (!list_empty(&conn->chan_l)) {
15609f0caeb1SVinicius Costa Gomes 			err = -EBUSY;
15619f0caeb1SVinicius Costa Gomes 			hci_conn_put(hcon);
15629f0caeb1SVinicius Costa Gomes 		}
15639f0caeb1SVinicius Costa Gomes 
15649f0caeb1SVinicius Costa Gomes 		if (err)
15659f0caeb1SVinicius Costa Gomes 			goto done;
15669f0caeb1SVinicius Costa Gomes 	}
15679f0caeb1SVinicius Costa Gomes 
15680a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
15690a708f8fSGustavo F. Padovan 	bacpy(src, conn->src);
15700a708f8fSGustavo F. Padovan 
15716be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
157248454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
15736be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
157448454079SGustavo F. Padovan 
15756be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
1576c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
15770a708f8fSGustavo F. Padovan 
15780a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1579715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1580c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1581d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
15826be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
15830a708f8fSGustavo F. Padovan 		} else
1584fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15850a708f8fSGustavo F. Padovan 	}
15860a708f8fSGustavo F. Padovan 
158730e76272SVille Tervo 	err = 0;
158830e76272SVille Tervo 
15890a708f8fSGustavo F. Padovan done:
15906be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
159109fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
15920a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
15930a708f8fSGustavo F. Padovan 	return err;
15940a708f8fSGustavo F. Padovan }
15950a708f8fSGustavo F. Padovan 
1596dcba0dbaSGustavo F. Padovan int __l2cap_wait_ack(struct sock *sk)
15970a708f8fSGustavo F. Padovan {
15988c1d787bSGustavo F. Padovan 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
15990a708f8fSGustavo F. Padovan 	DECLARE_WAITQUEUE(wait, current);
16000a708f8fSGustavo F. Padovan 	int err = 0;
16010a708f8fSGustavo F. Padovan 	int timeo = HZ/5;
16020a708f8fSGustavo F. Padovan 
16030a708f8fSGustavo F. Padovan 	add_wait_queue(sk_sleep(sk), &wait);
16040a708f8fSGustavo F. Padovan 	set_current_state(TASK_INTERRUPTIBLE);
1605a71a0cf4SPeter Hurley 	while (chan->unacked_frames > 0 && chan->conn) {
16060a708f8fSGustavo F. Padovan 		if (!timeo)
16070a708f8fSGustavo F. Padovan 			timeo = HZ/5;
16080a708f8fSGustavo F. Padovan 
16090a708f8fSGustavo F. Padovan 		if (signal_pending(current)) {
16100a708f8fSGustavo F. Padovan 			err = sock_intr_errno(timeo);
16110a708f8fSGustavo F. Padovan 			break;
16120a708f8fSGustavo F. Padovan 		}
16130a708f8fSGustavo F. Padovan 
16140a708f8fSGustavo F. Padovan 		release_sock(sk);
16150a708f8fSGustavo F. Padovan 		timeo = schedule_timeout(timeo);
16160a708f8fSGustavo F. Padovan 		lock_sock(sk);
1617a71a0cf4SPeter Hurley 		set_current_state(TASK_INTERRUPTIBLE);
16180a708f8fSGustavo F. Padovan 
16190a708f8fSGustavo F. Padovan 		err = sock_error(sk);
16200a708f8fSGustavo F. Padovan 		if (err)
16210a708f8fSGustavo F. Padovan 			break;
16220a708f8fSGustavo F. Padovan 	}
16230a708f8fSGustavo F. Padovan 	set_current_state(TASK_RUNNING);
16240a708f8fSGustavo F. Padovan 	remove_wait_queue(sk_sleep(sk), &wait);
16250a708f8fSGustavo F. Padovan 	return err;
16260a708f8fSGustavo F. Padovan }
16270a708f8fSGustavo F. Padovan 
1628721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
16290a708f8fSGustavo F. Padovan {
1630721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1631721c4181SGustavo F. Padovan 					       monitor_timer.work);
16320a708f8fSGustavo F. Padovan 
1633525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
16340a708f8fSGustavo F. Padovan 
16356be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16366be36555SAndrei Emeltchenko 
163780909e04SMat Martineau 	if (!chan->conn) {
16386be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16398d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
16400a708f8fSGustavo F. Padovan 		return;
16410a708f8fSGustavo F. Padovan 	}
16420a708f8fSGustavo F. Padovan 
1643401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
16440a708f8fSGustavo F. Padovan 
16456be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16468d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16470a708f8fSGustavo F. Padovan }
16480a708f8fSGustavo F. Padovan 
1649721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
16500a708f8fSGustavo F. Padovan {
1651721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1652721c4181SGustavo F. Padovan 					       retrans_timer.work);
16530a708f8fSGustavo F. Padovan 
165449208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
16550a708f8fSGustavo F. Padovan 
16566be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
16576be36555SAndrei Emeltchenko 
165880909e04SMat Martineau 	if (!chan->conn) {
165980909e04SMat Martineau 		l2cap_chan_unlock(chan);
166080909e04SMat Martineau 		l2cap_chan_put(chan);
166180909e04SMat Martineau 		return;
166280909e04SMat Martineau 	}
16630a708f8fSGustavo F. Padovan 
1664401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
16656be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
16668d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
16670a708f8fSGustavo F. Padovan }
16680a708f8fSGustavo F. Padovan 
1669d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
16703733937dSMat Martineau 				 struct sk_buff_head *skbs)
16710a708f8fSGustavo F. Padovan {
16720a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
16733733937dSMat Martineau 	struct l2cap_ctrl *control;
16740a708f8fSGustavo F. Padovan 
16753733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
16763733937dSMat Martineau 
16773733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
16783733937dSMat Martineau 
16793733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
16803733937dSMat Martineau 
16813733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
16823733937dSMat Martineau 
16833733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
16843733937dSMat Martineau 		control = &bt_cb(skb)->control;
16853733937dSMat Martineau 
16863733937dSMat Martineau 		control->reqseq = 0;
16873733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
16883733937dSMat Martineau 
16893733937dSMat Martineau 		__pack_control(chan, control, skb);
16900a708f8fSGustavo F. Padovan 
169147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
16923733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
16933733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
16940a708f8fSGustavo F. Padovan 		}
16950a708f8fSGustavo F. Padovan 
16964343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
16970a708f8fSGustavo F. Padovan 
16983733937dSMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
16993733937dSMat Martineau 
1700836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17013733937dSMat Martineau 		chan->frames_sent++;
17020a708f8fSGustavo F. Padovan 	}
17030a708f8fSGustavo F. Padovan }
17040a708f8fSGustavo F. Padovan 
170567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
17060a708f8fSGustavo F. Padovan {
17070a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
170818a48e76SMat Martineau 	struct l2cap_ctrl *control;
170918a48e76SMat Martineau 	int sent = 0;
171018a48e76SMat Martineau 
171118a48e76SMat Martineau 	BT_DBG("chan %p", chan);
17120a708f8fSGustavo F. Padovan 
171389bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
17140a708f8fSGustavo F. Padovan 		return -ENOTCONN;
17150a708f8fSGustavo F. Padovan 
171694122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
171794122bbeSMat Martineau 		return 0;
171894122bbeSMat Martineau 
171918a48e76SMat Martineau 	while (chan->tx_send_head &&
172018a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
172118a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
17220a708f8fSGustavo F. Padovan 
172318a48e76SMat Martineau 		skb = chan->tx_send_head;
17240a708f8fSGustavo F. Padovan 
172518a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
172618a48e76SMat Martineau 		control = &bt_cb(skb)->control;
17270a708f8fSGustavo F. Padovan 
1728e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
172918a48e76SMat Martineau 			control->final = 1;
1730e2ab4353SGustavo F. Padovan 
173118a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
173218a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
173318a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
17340a708f8fSGustavo F. Padovan 
173518a48e76SMat Martineau 		__pack_control(chan, control, skb);
17360a708f8fSGustavo F. Padovan 
173747d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
173818a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
173918a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
17400a708f8fSGustavo F. Padovan 		}
17410a708f8fSGustavo F. Padovan 
174218a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
174318a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
174418a48e76SMat Martineau 		 */
174518a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
174618a48e76SMat Martineau 
174718a48e76SMat Martineau 		if (!tx_skb)
174818a48e76SMat Martineau 			break;
17490a708f8fSGustavo F. Padovan 
17501a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
17510a708f8fSGustavo F. Padovan 
1752836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
17536a026610SGustavo F. Padovan 		chan->unacked_frames++;
17546a026610SGustavo F. Padovan 		chan->frames_sent++;
175518a48e76SMat Martineau 		sent++;
17560a708f8fSGustavo F. Padovan 
175758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
175858d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
17590a708f8fSGustavo F. Padovan 		else
176058d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
176118a48e76SMat Martineau 
176218a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
176318a48e76SMat Martineau 		BT_DBG("Sent txseq %d", (int)control->txseq);
17640a708f8fSGustavo F. Padovan 	}
17650a708f8fSGustavo F. Padovan 
176618a48e76SMat Martineau 	BT_DBG("Sent %d, %d unacked, %d in ERTM queue", sent,
176718a48e76SMat Martineau 	       (int) chan->unacked_frames, skb_queue_len(&chan->tx_q));
176818a48e76SMat Martineau 
176918a48e76SMat Martineau 	return sent;
17700a708f8fSGustavo F. Padovan }
17710a708f8fSGustavo F. Padovan 
1772e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
1773e1fbd4c1SMat Martineau {
1774e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
1775e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1776e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
1777e1fbd4c1SMat Martineau 	u16 seq;
1778e1fbd4c1SMat Martineau 
1779e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
1780e1fbd4c1SMat Martineau 
1781e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1782e1fbd4c1SMat Martineau 		return;
1783e1fbd4c1SMat Martineau 
1784e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
1785e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
1786e1fbd4c1SMat Martineau 
1787e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
1788e1fbd4c1SMat Martineau 		if (!skb) {
1789e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
1790e1fbd4c1SMat Martineau 				seq);
1791e1fbd4c1SMat Martineau 			continue;
1792e1fbd4c1SMat Martineau 		}
1793e1fbd4c1SMat Martineau 
1794e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
1795e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
1796e1fbd4c1SMat Martineau 
1797e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
1798e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
1799e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
1800e1fbd4c1SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
1801e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1802e1fbd4c1SMat Martineau 			break;
1803e1fbd4c1SMat Martineau 		}
1804e1fbd4c1SMat Martineau 
1805e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
1806e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
1807e1fbd4c1SMat Martineau 			control.final = 1;
1808e1fbd4c1SMat Martineau 		else
1809e1fbd4c1SMat Martineau 			control.final = 0;
1810e1fbd4c1SMat Martineau 
1811e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
1812e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
1813e1fbd4c1SMat Martineau 			 * writeable copy
1814e1fbd4c1SMat Martineau 			 */
1815e1fbd4c1SMat Martineau 			tx_skb = skb_copy(skb, GFP_ATOMIC);
1816e1fbd4c1SMat Martineau 		} else {
1817e1fbd4c1SMat Martineau 			tx_skb = skb_clone(skb, GFP_ATOMIC);
1818e1fbd4c1SMat Martineau 		}
1819e1fbd4c1SMat Martineau 
1820e1fbd4c1SMat Martineau 		if (!tx_skb) {
1821e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
1822e1fbd4c1SMat Martineau 			break;
1823e1fbd4c1SMat Martineau 		}
1824e1fbd4c1SMat Martineau 
1825e1fbd4c1SMat Martineau 		/* Update skb contents */
1826e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1827e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
1828e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1829e1fbd4c1SMat Martineau 		} else {
1830e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
1831e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
1832e1fbd4c1SMat Martineau 		}
1833e1fbd4c1SMat Martineau 
1834e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
1835e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
1836e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
1837e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
1838e1fbd4c1SMat Martineau 		}
1839e1fbd4c1SMat Martineau 
1840e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
1841e1fbd4c1SMat Martineau 
1842e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
1843e1fbd4c1SMat Martineau 
1844e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
1845e1fbd4c1SMat Martineau 	}
1846e1fbd4c1SMat Martineau }
1847e1fbd4c1SMat Martineau 
1848f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
1849f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
1850f80842a8SMat Martineau {
1851f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1852f80842a8SMat Martineau 
1853f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
1854f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
1855f80842a8SMat Martineau }
1856f80842a8SMat Martineau 
1857d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
1858d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
1859d2a7ac5dSMat Martineau {
1860e1fbd4c1SMat Martineau 	struct sk_buff *skb;
1861e1fbd4c1SMat Martineau 
1862e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1863e1fbd4c1SMat Martineau 
1864e1fbd4c1SMat Martineau 	if (control->poll)
1865e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
1866e1fbd4c1SMat Martineau 
1867e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
1868e1fbd4c1SMat Martineau 
1869e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
1870e1fbd4c1SMat Martineau 		return;
1871e1fbd4c1SMat Martineau 
1872e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
1873e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
1874e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
1875e1fbd4c1SMat Martineau 				skb == chan->tx_send_head)
1876e1fbd4c1SMat Martineau 				break;
1877e1fbd4c1SMat Martineau 		}
1878e1fbd4c1SMat Martineau 
1879e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
1880e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
1881e1fbd4c1SMat Martineau 				break;
1882e1fbd4c1SMat Martineau 
1883e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
1884e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
1885e1fbd4c1SMat Martineau 		}
1886e1fbd4c1SMat Martineau 
1887e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
1888e1fbd4c1SMat Martineau 	}
1889d2a7ac5dSMat Martineau }
1890d2a7ac5dSMat Martineau 
1891b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
1892b17e73bbSSzymon Janc {
18930a0aba42SMat Martineau 	struct l2cap_ctrl control;
18940a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
18950a0aba42SMat Martineau 					 chan->last_acked_seq);
18960a0aba42SMat Martineau 	int threshold;
18970a0aba42SMat Martineau 
18980a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
18990a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
19000a0aba42SMat Martineau 
19010a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
19020a0aba42SMat Martineau 	control.sframe = 1;
19030a0aba42SMat Martineau 
19040a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
19050a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
1906b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
19070a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
19080a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
19090a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
19100a0aba42SMat Martineau 	} else {
19110a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
19120a0aba42SMat Martineau 			l2cap_ertm_send(chan);
19130a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
19140a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
19150a0aba42SMat Martineau 				frames_to_ack = 0;
19160a0aba42SMat Martineau 		}
19170a0aba42SMat Martineau 
19180a0aba42SMat Martineau 		/* Ack now if the tx window is 3/4ths full.
19190a0aba42SMat Martineau 		 * Calculate without mul or div
19200a0aba42SMat Martineau 		 */
19210a0aba42SMat Martineau 		threshold = chan->tx_win;
19220a0aba42SMat Martineau 		threshold += threshold << 1;
19230a0aba42SMat Martineau 		threshold >>= 2;
19240a0aba42SMat Martineau 
19250a0aba42SMat Martineau 		BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
19260a0aba42SMat Martineau 		       threshold);
19270a0aba42SMat Martineau 
19280a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
19290a0aba42SMat Martineau 			__clear_ack_timer(chan);
19300a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
19310a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
19320a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
19330a0aba42SMat Martineau 			frames_to_ack = 0;
19340a0aba42SMat Martineau 		}
19350a0aba42SMat Martineau 
19360a0aba42SMat Martineau 		if (frames_to_ack)
19370a0aba42SMat Martineau 			__set_ack_timer(chan);
19380a0aba42SMat Martineau 	}
1939b17e73bbSSzymon Janc }
1940b17e73bbSSzymon Janc 
194104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
194204124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
194304124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
19440a708f8fSGustavo F. Padovan {
19450952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
19460a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
194790338947SGustavo Padovan 	int sent = 0;
19480a708f8fSGustavo F. Padovan 
19490a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
19500a708f8fSGustavo F. Padovan 		return -EFAULT;
19510a708f8fSGustavo F. Padovan 
19520a708f8fSGustavo F. Padovan 	sent += count;
19530a708f8fSGustavo F. Padovan 	len  -= count;
19540a708f8fSGustavo F. Padovan 
19550a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
19560a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
19570a708f8fSGustavo F. Padovan 	while (len) {
1958fbe00700SGustavo Padovan 		struct sk_buff *tmp;
1959fbe00700SGustavo Padovan 
19600a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
19610a708f8fSGustavo F. Padovan 
1962fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
196390338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
1964fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
1965fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
19662f7719ceSAndrei Emeltchenko 
1967fbe00700SGustavo Padovan 		*frag = tmp;
1968fbe00700SGustavo Padovan 
19690a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
19700a708f8fSGustavo F. Padovan 			return -EFAULT;
19710a708f8fSGustavo F. Padovan 
19725e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
19735e59b791SLuiz Augusto von Dentz 
19740a708f8fSGustavo F. Padovan 		sent += count;
19750a708f8fSGustavo F. Padovan 		len  -= count;
19760a708f8fSGustavo F. Padovan 
19772d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
19782d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
19792d0ed3d5SGustavo Padovan 
19800a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
19810a708f8fSGustavo F. Padovan 	}
19820a708f8fSGustavo F. Padovan 
19830a708f8fSGustavo F. Padovan 	return sent;
19840a708f8fSGustavo F. Padovan }
19850a708f8fSGustavo F. Padovan 
19865e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
19875e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
19885e59b791SLuiz Augusto von Dentz 						u32 priority)
19890a708f8fSGustavo F. Padovan {
19908c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
19910a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
199203a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
19930a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
19940a708f8fSGustavo F. Padovan 
19956d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d priority %u", chan, (int)len, priority);
19960a708f8fSGustavo F. Padovan 
19970a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
19982f7719ceSAndrei Emeltchenko 
19992f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
200090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
200190338947SGustavo Padovan 	if (IS_ERR(skb))
200290338947SGustavo Padovan 		return skb;
20030a708f8fSGustavo F. Padovan 
20045e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20055e59b791SLuiz Augusto von Dentz 
20060a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20070a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2008fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2009daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
2010daf6a78cSAndrei Emeltchenko 	put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE));
20110a708f8fSGustavo F. Padovan 
20120952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20130a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20140a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20150a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20160a708f8fSGustavo F. Padovan 	}
20170a708f8fSGustavo F. Padovan 	return skb;
20180a708f8fSGustavo F. Padovan }
20190a708f8fSGustavo F. Padovan 
20205e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
20215e59b791SLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
20225e59b791SLuiz Augusto von Dentz 						u32 priority)
20230a708f8fSGustavo F. Padovan {
20248c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20250a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2026f2ba7faeSGustavo Padovan 	int err, count;
20270a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20280a708f8fSGustavo F. Padovan 
20296d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20300a708f8fSGustavo F. Padovan 
2031f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
20322f7719ceSAndrei Emeltchenko 
2033f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
203490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
203590338947SGustavo Padovan 	if (IS_ERR(skb))
203690338947SGustavo Padovan 		return skb;
20370a708f8fSGustavo F. Padovan 
20385e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
20395e59b791SLuiz Augusto von Dentz 
20400a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20410a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2042fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20436ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
20440a708f8fSGustavo F. Padovan 
20450952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
20460a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
20470a708f8fSGustavo F. Padovan 		kfree_skb(skb);
20480a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
20490a708f8fSGustavo F. Padovan 	}
20500a708f8fSGustavo F. Padovan 	return skb;
20510a708f8fSGustavo F. Padovan }
20520a708f8fSGustavo F. Padovan 
2053ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2054ab0ff76dSLuiz Augusto von Dentz 						struct msghdr *msg, size_t len,
205594122bbeSMat Martineau 						u16 sdulen)
20560a708f8fSGustavo F. Padovan {
20578c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
20580a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2059e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
20600a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
20610a708f8fSGustavo F. Padovan 
20626d5922b0SAndrei Emeltchenko 	BT_DBG("chan %p len %d", chan, (int)len);
20630a708f8fSGustavo F. Padovan 
20640a708f8fSGustavo F. Padovan 	if (!conn)
20650a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
20660a708f8fSGustavo F. Padovan 
2067e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
2068e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_EXT_HDR_SIZE;
2069e4ca6d98SAndrei Emeltchenko 	else
2070e4ca6d98SAndrei Emeltchenko 		hlen = L2CAP_ENH_HDR_SIZE;
2071e4ca6d98SAndrei Emeltchenko 
20720a708f8fSGustavo F. Padovan 	if (sdulen)
207303a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
20740a708f8fSGustavo F. Padovan 
207547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
207603a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
20770a708f8fSGustavo F. Padovan 
20780a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
20792f7719ceSAndrei Emeltchenko 
20802f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
208190338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
208290338947SGustavo Padovan 	if (IS_ERR(skb))
208390338947SGustavo Padovan 		return skb;
20840a708f8fSGustavo F. Padovan 
20850a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
20860a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2087fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
20880a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
208988843ab0SAndrei Emeltchenko 
209018a48e76SMat Martineau 	/* Control header is populated later */
209118a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
209218a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
209318a48e76SMat Martineau 	else
209418a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
209588843ab0SAndrei Emeltchenko 
20960a708f8fSGustavo F. Padovan 	if (sdulen)
209703a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
20980a708f8fSGustavo F. Padovan 
20990952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
21000a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
21010a708f8fSGustavo F. Padovan 		kfree_skb(skb);
21020a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
21030a708f8fSGustavo F. Padovan 	}
21040a708f8fSGustavo F. Padovan 
210518a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
21063ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
21070a708f8fSGustavo F. Padovan 	return skb;
21080a708f8fSGustavo F. Padovan }
21090a708f8fSGustavo F. Padovan 
211094122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
211194122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
211294122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
21130a708f8fSGustavo F. Padovan {
21140a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
211594122bbeSMat Martineau 	u16 sdu_len;
211694122bbeSMat Martineau 	size_t pdu_len;
211794122bbeSMat Martineau 	int err = 0;
211894122bbeSMat Martineau 	u8 sar;
21190a708f8fSGustavo F. Padovan 
212094122bbeSMat Martineau 	BT_DBG("chan %p, msg %p, len %d", chan, msg, (int)len);
21210a708f8fSGustavo F. Padovan 
212294122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
212394122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
212494122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
212594122bbeSMat Martineau 	 */
212694122bbeSMat Martineau 
212794122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
212894122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
212994122bbeSMat Martineau 
213094122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
213194122bbeSMat Martineau 
213294122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
213394122bbeSMat Martineau 	pdu_len -= L2CAP_EXT_HDR_SIZE + L2CAP_FCS_SIZE;
213494122bbeSMat Martineau 
213594122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
213694122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
213794122bbeSMat Martineau 
213894122bbeSMat Martineau 	if (len <= pdu_len) {
213994122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
214094122bbeSMat Martineau 		sdu_len = 0;
214194122bbeSMat Martineau 		pdu_len = len;
214294122bbeSMat Martineau 	} else {
214394122bbeSMat Martineau 		sar = L2CAP_SAR_START;
214494122bbeSMat Martineau 		sdu_len = len;
214594122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
214694122bbeSMat Martineau 	}
21470a708f8fSGustavo F. Padovan 
21480a708f8fSGustavo F. Padovan 	while (len > 0) {
214994122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
21500a708f8fSGustavo F. Padovan 
21510a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
215294122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
21530a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
21540a708f8fSGustavo F. Padovan 		}
21550a708f8fSGustavo F. Padovan 
215694122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
215794122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
21580a708f8fSGustavo F. Padovan 
215994122bbeSMat Martineau 		len -= pdu_len;
216094122bbeSMat Martineau 		if (sdu_len) {
216194122bbeSMat Martineau 			sdu_len = 0;
216294122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
216394122bbeSMat Martineau 		}
216494122bbeSMat Martineau 
216594122bbeSMat Martineau 		if (len <= pdu_len) {
216694122bbeSMat Martineau 			sar = L2CAP_SAR_END;
216794122bbeSMat Martineau 			pdu_len = len;
216894122bbeSMat Martineau 		} else {
216994122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
217094122bbeSMat Martineau 		}
217194122bbeSMat Martineau 	}
217294122bbeSMat Martineau 
217394122bbeSMat Martineau 	return err;
21740a708f8fSGustavo F. Padovan }
21750a708f8fSGustavo F. Padovan 
21765e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
21775e59b791SLuiz Augusto von Dentz 								u32 priority)
21789a91a04aSGustavo F. Padovan {
21799a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
21809a91a04aSGustavo F. Padovan 	int err;
218194122bbeSMat Martineau 	struct sk_buff_head seg_queue;
21829a91a04aSGustavo F. Padovan 
21839a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2184715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
21855e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
21869a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
21879a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
21889a91a04aSGustavo F. Padovan 
21899a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
21909a91a04aSGustavo F. Padovan 		return len;
21919a91a04aSGustavo F. Padovan 	}
21929a91a04aSGustavo F. Padovan 
21939a91a04aSGustavo F. Padovan 	switch (chan->mode) {
21949a91a04aSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
21959a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
21969a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
21979a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
21989a91a04aSGustavo F. Padovan 
21999a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
22005e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
22019a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
22029a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
22039a91a04aSGustavo F. Padovan 
22049a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
22059a91a04aSGustavo F. Padovan 		err = len;
22069a91a04aSGustavo F. Padovan 		break;
22079a91a04aSGustavo F. Padovan 
22089a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
22099a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
221094122bbeSMat Martineau 		/* Check outgoing MTU */
221194122bbeSMat Martineau 		if (len > chan->omtu) {
221294122bbeSMat Martineau 			err = -EMSGSIZE;
22139a91a04aSGustavo F. Padovan 			break;
22149a91a04aSGustavo F. Padovan 		}
22159a91a04aSGustavo F. Padovan 
221694122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
221794122bbeSMat Martineau 
221894122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
221994122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
222094122bbeSMat Martineau 		 * allocation.
222194122bbeSMat Martineau 		 */
222294122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
222394122bbeSMat Martineau 
222494122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
222594122bbeSMat Martineau 		 * check that it is still connected.
222694122bbeSMat Martineau 		 */
222794122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
222894122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
222994122bbeSMat Martineau 			err = -ENOTCONN;
22309a91a04aSGustavo F. Padovan 		}
22319a91a04aSGustavo F. Padovan 
223294122bbeSMat Martineau 		if (err)
223394122bbeSMat Martineau 			break;
223494122bbeSMat Martineau 
22353733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2236d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
22373733937dSMat Martineau 		else
2238d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
223994122bbeSMat Martineau 
22409a91a04aSGustavo F. Padovan 		err = len;
22419a91a04aSGustavo F. Padovan 
224294122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
224394122bbeSMat Martineau 		 * seg_queue and need to be purged.
224494122bbeSMat Martineau 		 */
224594122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
22469a91a04aSGustavo F. Padovan 		break;
22479a91a04aSGustavo F. Padovan 
22489a91a04aSGustavo F. Padovan 	default:
22499a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
22509a91a04aSGustavo F. Padovan 		err = -EBADFD;
22519a91a04aSGustavo F. Padovan 	}
22529a91a04aSGustavo F. Padovan 
22539a91a04aSGustavo F. Padovan 	return err;
22549a91a04aSGustavo F. Padovan }
22559a91a04aSGustavo F. Padovan 
2256d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2257d2a7ac5dSMat Martineau {
2258bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2259bed68bdeSMat Martineau 	u16 seq;
2260bed68bdeSMat Martineau 
2261bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2262bed68bdeSMat Martineau 
2263bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2264bed68bdeSMat Martineau 	control.sframe = 1;
2265bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2266bed68bdeSMat Martineau 
2267bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2268bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2269bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2270bed68bdeSMat Martineau 			control.reqseq = seq;
2271bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2272bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2273bed68bdeSMat Martineau 		}
2274bed68bdeSMat Martineau 	}
2275bed68bdeSMat Martineau 
2276bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2277d2a7ac5dSMat Martineau }
2278d2a7ac5dSMat Martineau 
2279d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2280d2a7ac5dSMat Martineau {
2281bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2282bed68bdeSMat Martineau 
2283bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2284bed68bdeSMat Martineau 
2285bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2286bed68bdeSMat Martineau 		return;
2287bed68bdeSMat Martineau 
2288bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2289bed68bdeSMat Martineau 	control.sframe = 1;
2290bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2291bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2292bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2293d2a7ac5dSMat Martineau }
2294d2a7ac5dSMat Martineau 
2295d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2296d2a7ac5dSMat Martineau {
2297bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2298bed68bdeSMat Martineau 	u16 initial_head;
2299bed68bdeSMat Martineau 	u16 seq;
2300bed68bdeSMat Martineau 
2301bed68bdeSMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
2302bed68bdeSMat Martineau 
2303bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2304bed68bdeSMat Martineau 	control.sframe = 1;
2305bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2306bed68bdeSMat Martineau 
2307bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2308bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2309bed68bdeSMat Martineau 
2310bed68bdeSMat Martineau 	do {
2311bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2312bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2313bed68bdeSMat Martineau 			break;
2314bed68bdeSMat Martineau 
2315bed68bdeSMat Martineau 		control.reqseq = seq;
2316bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2317bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2318bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2319d2a7ac5dSMat Martineau }
2320d2a7ac5dSMat Martineau 
2321608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2322608bcc6dSMat Martineau {
2323608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2324608bcc6dSMat Martineau 	u16 ackseq;
2325608bcc6dSMat Martineau 
2326608bcc6dSMat Martineau 	BT_DBG("chan %p, reqseq %d", chan, reqseq);
2327608bcc6dSMat Martineau 
2328608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2329608bcc6dSMat Martineau 		return;
2330608bcc6dSMat Martineau 
2331608bcc6dSMat Martineau 	BT_DBG("expected_ack_seq %d, unacked_frames %d",
2332608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2333608bcc6dSMat Martineau 
2334608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2335608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2336608bcc6dSMat Martineau 
2337608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2338608bcc6dSMat Martineau 		if (acked_skb) {
2339608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2340608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2341608bcc6dSMat Martineau 			chan->unacked_frames--;
2342608bcc6dSMat Martineau 		}
2343608bcc6dSMat Martineau 	}
2344608bcc6dSMat Martineau 
2345608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2346608bcc6dSMat Martineau 
2347608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2348608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2349608bcc6dSMat Martineau 
2350608bcc6dSMat Martineau 	BT_DBG("unacked_frames %d", (int) chan->unacked_frames);
2351608bcc6dSMat Martineau }
2352608bcc6dSMat Martineau 
2353608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2354608bcc6dSMat Martineau {
2355608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2356608bcc6dSMat Martineau 
2357608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2358608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2359608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2360608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2361608bcc6dSMat Martineau }
2362608bcc6dSMat Martineau 
2363d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2364608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2365608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2366608bcc6dSMat Martineau {
2367608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2368608bcc6dSMat Martineau 	       event);
2369608bcc6dSMat Martineau 
2370608bcc6dSMat Martineau 	switch (event) {
2371608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2372608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2373608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2374608bcc6dSMat Martineau 
2375608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2376608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2377608bcc6dSMat Martineau 		break;
2378608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2379608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2380608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2381608bcc6dSMat Martineau 
2382608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2383608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2384608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2385608bcc6dSMat Martineau 			 */
2386608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2387608bcc6dSMat Martineau 		}
2388608bcc6dSMat Martineau 
2389608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2390608bcc6dSMat Martineau 
2391608bcc6dSMat Martineau 		break;
2392608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2393608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2394608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2395608bcc6dSMat Martineau 
2396608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2397608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2398608bcc6dSMat Martineau 
2399608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2400608bcc6dSMat Martineau 			local_control.sframe = 1;
2401608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2402608bcc6dSMat Martineau 			local_control.poll = 1;
2403608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2404a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2405608bcc6dSMat Martineau 
2406608bcc6dSMat Martineau 			chan->retry_count = 1;
2407608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2408608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2409608bcc6dSMat Martineau 		}
2410608bcc6dSMat Martineau 		break;
2411608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2412608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2413608bcc6dSMat Martineau 		break;
2414608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2415608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2416608bcc6dSMat Martineau 		chan->retry_count = 1;
2417608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2418608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2419608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2420608bcc6dSMat Martineau 		break;
2421608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2422608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2423608bcc6dSMat Martineau 		chan->retry_count = 1;
2424608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2425608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2426608bcc6dSMat Martineau 		break;
2427608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2428608bcc6dSMat Martineau 		/* Nothing to process */
2429608bcc6dSMat Martineau 		break;
2430608bcc6dSMat Martineau 	default:
2431608bcc6dSMat Martineau 		break;
2432608bcc6dSMat Martineau 	}
2433608bcc6dSMat Martineau }
2434608bcc6dSMat Martineau 
2435d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2436608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2437608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2438608bcc6dSMat Martineau {
2439608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2440608bcc6dSMat Martineau 	       event);
2441608bcc6dSMat Martineau 
2442608bcc6dSMat Martineau 	switch (event) {
2443608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2444608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2445608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2446608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2447608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2448608bcc6dSMat Martineau 		break;
2449608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2450608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2451608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2452608bcc6dSMat Martineau 
2453608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2454608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2455608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2456608bcc6dSMat Martineau 			 */
2457608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2458608bcc6dSMat Martineau 		}
2459608bcc6dSMat Martineau 
2460608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2461608bcc6dSMat Martineau 
2462608bcc6dSMat Martineau 		break;
2463608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2464608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2465608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2466608bcc6dSMat Martineau 
2467608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2468608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2469608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2470608bcc6dSMat Martineau 			local_control.sframe = 1;
2471608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2472608bcc6dSMat Martineau 			local_control.poll = 1;
2473608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2474a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2475608bcc6dSMat Martineau 
2476608bcc6dSMat Martineau 			chan->retry_count = 1;
2477608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2478608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2479608bcc6dSMat Martineau 		}
2480608bcc6dSMat Martineau 		break;
2481608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2482608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2483608bcc6dSMat Martineau 
2484608bcc6dSMat Martineau 		/* Fall through */
2485608bcc6dSMat Martineau 
2486608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2487608bcc6dSMat Martineau 		if (control && control->final) {
2488608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2489608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2490608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2491608bcc6dSMat Martineau 			chan->retry_count = 0;
2492608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2493608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2494608bcc6dSMat Martineau 		}
2495608bcc6dSMat Martineau 		break;
2496608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2497608bcc6dSMat Martineau 		/* Ignore */
2498608bcc6dSMat Martineau 		break;
2499608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
2500608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
2501608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
2502608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2503608bcc6dSMat Martineau 			chan->retry_count++;
2504608bcc6dSMat Martineau 		} else {
2505608bcc6dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
2506608bcc6dSMat Martineau 		}
2507608bcc6dSMat Martineau 		break;
2508608bcc6dSMat Martineau 	default:
2509608bcc6dSMat Martineau 		break;
2510608bcc6dSMat Martineau 	}
2511608bcc6dSMat Martineau }
2512608bcc6dSMat Martineau 
2513d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
2514608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
2515608bcc6dSMat Martineau {
2516608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
2517608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
2518608bcc6dSMat Martineau 
2519608bcc6dSMat Martineau 	switch (chan->tx_state) {
2520608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
2521d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
2522608bcc6dSMat Martineau 		break;
2523608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
2524d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
2525608bcc6dSMat Martineau 		break;
2526608bcc6dSMat Martineau 	default:
2527608bcc6dSMat Martineau 		/* Ignore event */
2528608bcc6dSMat Martineau 		break;
2529608bcc6dSMat Martineau 	}
2530608bcc6dSMat Martineau }
2531608bcc6dSMat Martineau 
25324b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
25334b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
25344b51dae9SMat Martineau {
25354b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2536401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
25374b51dae9SMat Martineau }
25384b51dae9SMat Martineau 
2539f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
2540f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
2541f80842a8SMat Martineau {
2542f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2543401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
2544f80842a8SMat Martineau }
2545f80842a8SMat Martineau 
25460a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
25470a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
25480a708f8fSGustavo F. Padovan {
25490a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
255048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
25510a708f8fSGustavo F. Padovan 
25520a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
25530a708f8fSGustavo F. Padovan 
25543df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
25553d57dc68SGustavo F. Padovan 
25563df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
255748454079SGustavo F. Padovan 		struct sock *sk = chan->sk;
2558715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
25590a708f8fSGustavo F. Padovan 			continue;
25600a708f8fSGustavo F. Padovan 
25610a708f8fSGustavo F. Padovan 		/* Don't send frame to the socket it came from */
25620a708f8fSGustavo F. Padovan 		if (skb->sk == sk)
25630a708f8fSGustavo F. Padovan 			continue;
25640a708f8fSGustavo F. Padovan 		nskb = skb_clone(skb, GFP_ATOMIC);
25650a708f8fSGustavo F. Padovan 		if (!nskb)
25660a708f8fSGustavo F. Padovan 			continue;
25670a708f8fSGustavo F. Padovan 
256823070494SGustavo F. Padovan 		if (chan->ops->recv(chan->data, nskb))
25690a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
25700a708f8fSGustavo F. Padovan 	}
25713d57dc68SGustavo F. Padovan 
25723df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
25730a708f8fSGustavo F. Padovan }
25740a708f8fSGustavo F. Padovan 
25750a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
25760a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
25770a708f8fSGustavo F. Padovan 				u8 code, u8 ident, u16 dlen, void *data)
25780a708f8fSGustavo F. Padovan {
25790a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
25800a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
25810a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
25820a708f8fSGustavo F. Padovan 	int len, count;
25830a708f8fSGustavo F. Padovan 
25840a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
25850a708f8fSGustavo F. Padovan 			conn, code, ident, dlen);
25860a708f8fSGustavo F. Padovan 
25870a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
25880a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
25890a708f8fSGustavo F. Padovan 
25900a708f8fSGustavo F. Padovan 	skb = bt_skb_alloc(count, GFP_ATOMIC);
25910a708f8fSGustavo F. Padovan 	if (!skb)
25920a708f8fSGustavo F. Padovan 		return NULL;
25930a708f8fSGustavo F. Padovan 
25940a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
25950a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
25963300d9a9SClaudio Takahasi 
25973300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
25983300d9a9SClaudio Takahasi 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
25993300d9a9SClaudio Takahasi 	else
26000a708f8fSGustavo F. Padovan 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
26010a708f8fSGustavo F. Padovan 
26020a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
26030a708f8fSGustavo F. Padovan 	cmd->code  = code;
26040a708f8fSGustavo F. Padovan 	cmd->ident = ident;
26050a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
26060a708f8fSGustavo F. Padovan 
26070a708f8fSGustavo F. Padovan 	if (dlen) {
26080a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
26090a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
26100a708f8fSGustavo F. Padovan 		data += count;
26110a708f8fSGustavo F. Padovan 	}
26120a708f8fSGustavo F. Padovan 
26130a708f8fSGustavo F. Padovan 	len -= skb->len;
26140a708f8fSGustavo F. Padovan 
26150a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
26160a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
26170a708f8fSGustavo F. Padovan 	while (len) {
26180a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
26190a708f8fSGustavo F. Padovan 
26200a708f8fSGustavo F. Padovan 		*frag = bt_skb_alloc(count, GFP_ATOMIC);
26210a708f8fSGustavo F. Padovan 		if (!*frag)
26220a708f8fSGustavo F. Padovan 			goto fail;
26230a708f8fSGustavo F. Padovan 
26240a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
26250a708f8fSGustavo F. Padovan 
26260a708f8fSGustavo F. Padovan 		len  -= count;
26270a708f8fSGustavo F. Padovan 		data += count;
26280a708f8fSGustavo F. Padovan 
26290a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
26300a708f8fSGustavo F. Padovan 	}
26310a708f8fSGustavo F. Padovan 
26320a708f8fSGustavo F. Padovan 	return skb;
26330a708f8fSGustavo F. Padovan 
26340a708f8fSGustavo F. Padovan fail:
26350a708f8fSGustavo F. Padovan 	kfree_skb(skb);
26360a708f8fSGustavo F. Padovan 	return NULL;
26370a708f8fSGustavo F. Padovan }
26380a708f8fSGustavo F. Padovan 
26390a708f8fSGustavo F. Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
26400a708f8fSGustavo F. Padovan {
26410a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26420a708f8fSGustavo F. Padovan 	int len;
26430a708f8fSGustavo F. Padovan 
26440a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
26450a708f8fSGustavo F. Padovan 	*ptr += len;
26460a708f8fSGustavo F. Padovan 
26470a708f8fSGustavo F. Padovan 	*type = opt->type;
26480a708f8fSGustavo F. Padovan 	*olen = opt->len;
26490a708f8fSGustavo F. Padovan 
26500a708f8fSGustavo F. Padovan 	switch (opt->len) {
26510a708f8fSGustavo F. Padovan 	case 1:
26520a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
26530a708f8fSGustavo F. Padovan 		break;
26540a708f8fSGustavo F. Padovan 
26550a708f8fSGustavo F. Padovan 	case 2:
26560a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
26570a708f8fSGustavo F. Padovan 		break;
26580a708f8fSGustavo F. Padovan 
26590a708f8fSGustavo F. Padovan 	case 4:
26600a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
26610a708f8fSGustavo F. Padovan 		break;
26620a708f8fSGustavo F. Padovan 
26630a708f8fSGustavo F. Padovan 	default:
26640a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
26650a708f8fSGustavo F. Padovan 		break;
26660a708f8fSGustavo F. Padovan 	}
26670a708f8fSGustavo F. Padovan 
26680a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
26690a708f8fSGustavo F. Padovan 	return len;
26700a708f8fSGustavo F. Padovan }
26710a708f8fSGustavo F. Padovan 
26720a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
26730a708f8fSGustavo F. Padovan {
26740a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
26750a708f8fSGustavo F. Padovan 
26760a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
26770a708f8fSGustavo F. Padovan 
26780a708f8fSGustavo F. Padovan 	opt->type = type;
26790a708f8fSGustavo F. Padovan 	opt->len  = len;
26800a708f8fSGustavo F. Padovan 
26810a708f8fSGustavo F. Padovan 	switch (len) {
26820a708f8fSGustavo F. Padovan 	case 1:
26830a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
26840a708f8fSGustavo F. Padovan 		break;
26850a708f8fSGustavo F. Padovan 
26860a708f8fSGustavo F. Padovan 	case 2:
26870a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
26880a708f8fSGustavo F. Padovan 		break;
26890a708f8fSGustavo F. Padovan 
26900a708f8fSGustavo F. Padovan 	case 4:
26910a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
26920a708f8fSGustavo F. Padovan 		break;
26930a708f8fSGustavo F. Padovan 
26940a708f8fSGustavo F. Padovan 	default:
26950a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
26960a708f8fSGustavo F. Padovan 		break;
26970a708f8fSGustavo F. Padovan 	}
26980a708f8fSGustavo F. Padovan 
26990a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
27000a708f8fSGustavo F. Padovan }
27010a708f8fSGustavo F. Padovan 
2702f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
2703f89cef09SAndrei Emeltchenko {
2704f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
2705f89cef09SAndrei Emeltchenko 
2706f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
2707f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
2708f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
2709f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
2710f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2711f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2712f89cef09SAndrei Emeltchenko 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
2713f89cef09SAndrei Emeltchenko 		efs.flush_to	= cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO);
2714f89cef09SAndrei Emeltchenko 		break;
2715f89cef09SAndrei Emeltchenko 
2716f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
2717f89cef09SAndrei Emeltchenko 		efs.id		= 1;
2718f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
2719f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
2720f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
2721f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
2722f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
2723f89cef09SAndrei Emeltchenko 		break;
2724f89cef09SAndrei Emeltchenko 
2725f89cef09SAndrei Emeltchenko 	default:
2726f89cef09SAndrei Emeltchenko 		return;
2727f89cef09SAndrei Emeltchenko 	}
2728f89cef09SAndrei Emeltchenko 
2729f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
2730f89cef09SAndrei Emeltchenko 							(unsigned long) &efs);
2731f89cef09SAndrei Emeltchenko }
2732f89cef09SAndrei Emeltchenko 
2733721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
27340a708f8fSGustavo F. Padovan {
2735721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2736721c4181SGustavo F. Padovan 					       ack_timer.work);
27370362520bSMat Martineau 	u16 frames_to_ack;
27380a708f8fSGustavo F. Padovan 
27392fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
27402fb9b3d4SGustavo F. Padovan 
27416be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
27426be36555SAndrei Emeltchenko 
27430362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
27440362520bSMat Martineau 				     chan->last_acked_seq);
27450362520bSMat Martineau 
27460362520bSMat Martineau 	if (frames_to_ack)
27470362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
27486be36555SAndrei Emeltchenko 
27496be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
275009bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
27510a708f8fSGustavo F. Padovan }
27520a708f8fSGustavo F. Padovan 
27533c588192SMat Martineau static inline int l2cap_ertm_init(struct l2cap_chan *chan)
27540a708f8fSGustavo F. Padovan {
27553c588192SMat Martineau 	int err;
27563c588192SMat Martineau 
2757105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
2758105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
275942e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
27606a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
276142e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
27626a026610SGustavo F. Padovan 	chan->frames_sent = 0;
2763105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
2764105bdf9eSMat Martineau 	chan->sdu = NULL;
2765105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
2766105bdf9eSMat Martineau 	chan->sdu_len = 0;
2767105bdf9eSMat Martineau 
2768d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
2769d34c34fbSMat Martineau 
2770105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
2771105bdf9eSMat Martineau 		return 0;
2772105bdf9eSMat Martineau 
2773105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2774105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
27750a708f8fSGustavo F. Padovan 
2776721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
2777721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
2778721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
27790a708f8fSGustavo F. Padovan 
2780f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
27810a708f8fSGustavo F. Padovan 
27823c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
27833c588192SMat Martineau 	if (err < 0)
27843c588192SMat Martineau 		return err;
27853c588192SMat Martineau 
27869dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
27879dc9affcSMat Martineau 	if (err < 0)
27889dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
27899dc9affcSMat Martineau 
27909dc9affcSMat Martineau 	return err;
27910a708f8fSGustavo F. Padovan }
27920a708f8fSGustavo F. Padovan 
27930a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
27940a708f8fSGustavo F. Padovan {
27950a708f8fSGustavo F. Padovan 	switch (mode) {
27960a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
27970a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27980a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
27990a708f8fSGustavo F. Padovan 			return mode;
28000a708f8fSGustavo F. Padovan 		/* fall through */
28010a708f8fSGustavo F. Padovan 	default:
28020a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
28030a708f8fSGustavo F. Padovan 	}
28040a708f8fSGustavo F. Padovan }
28050a708f8fSGustavo F. Padovan 
28066327eb98SAndrei Emeltchenko static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
28076327eb98SAndrei Emeltchenko {
28086327eb98SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
28096327eb98SAndrei Emeltchenko }
28106327eb98SAndrei Emeltchenko 
2811f89cef09SAndrei Emeltchenko static inline bool __l2cap_efs_supported(struct l2cap_chan *chan)
2812f89cef09SAndrei Emeltchenko {
2813f89cef09SAndrei Emeltchenko 	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
2814f89cef09SAndrei Emeltchenko }
2815f89cef09SAndrei Emeltchenko 
28166327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
28176327eb98SAndrei Emeltchenko {
28186327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
2819836be934SAndrei Emeltchenko 						__l2cap_ews_supported(chan)) {
28206327eb98SAndrei Emeltchenko 		/* use extended control field */
28216327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
2822836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
2823836be934SAndrei Emeltchenko 	} else {
28246327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
28256327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
2826836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
2827836be934SAndrei Emeltchenko 	}
28286327eb98SAndrei Emeltchenko }
28296327eb98SAndrei Emeltchenko 
2830710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
28310a708f8fSGustavo F. Padovan {
28320a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
28330c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
28340a708f8fSGustavo F. Padovan 	void *ptr = req->data;
2835c8f79162SAndrei Emeltchenko 	u16 size;
28360a708f8fSGustavo F. Padovan 
283749208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
28380a708f8fSGustavo F. Padovan 
283973ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
28400a708f8fSGustavo F. Padovan 		goto done;
28410a708f8fSGustavo F. Padovan 
28420c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28430a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
28440a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
2845c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
28460a708f8fSGustavo F. Padovan 			break;
28470a708f8fSGustavo F. Padovan 
2848f89cef09SAndrei Emeltchenko 		if (__l2cap_efs_supported(chan))
2849f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
2850f89cef09SAndrei Emeltchenko 
28510a708f8fSGustavo F. Padovan 		/* fall through */
28520a708f8fSGustavo F. Padovan 	default:
28538c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
28540a708f8fSGustavo F. Padovan 		break;
28550a708f8fSGustavo F. Padovan 	}
28560a708f8fSGustavo F. Padovan 
28570a708f8fSGustavo F. Padovan done:
28580c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
28590c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
28600a708f8fSGustavo F. Padovan 
28610c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
28620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
28638c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
28648c1d787bSGustavo F. Padovan 				!(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
28650a708f8fSGustavo F. Padovan 			break;
28660a708f8fSGustavo F. Padovan 
28670a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
28680a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
28690a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
28700a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28710a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
28720a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
28730a708f8fSGustavo F. Padovan 
28740a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28750a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28760a708f8fSGustavo F. Padovan 		break;
28770a708f8fSGustavo F. Padovan 
28780a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
28790a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
288047d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
28810a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
28820a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2883c8f79162SAndrei Emeltchenko 
2884c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2885c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2886c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2887c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2888c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
28890a708f8fSGustavo F. Padovan 
28906327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
28916327eb98SAndrei Emeltchenko 
28926327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
28936327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_TX_WINDOW);
28940a708f8fSGustavo F. Padovan 
28950a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
28960a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
28970a708f8fSGustavo F. Padovan 
2898f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2899f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2900f89cef09SAndrei Emeltchenko 
29018c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29020a708f8fSGustavo F. Padovan 			break;
29030a708f8fSGustavo F. Padovan 
290447d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2905c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
290647d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
290747d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29080a708f8fSGustavo F. Padovan 		}
29096327eb98SAndrei Emeltchenko 
29106327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
29116327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
29126327eb98SAndrei Emeltchenko 								chan->tx_win);
29130a708f8fSGustavo F. Padovan 		break;
29140a708f8fSGustavo F. Padovan 
29150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
2916273759e2SMat Martineau 		l2cap_txwin_setup(chan);
29170a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
29180a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
29190a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
29200a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
29210a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
2922c8f79162SAndrei Emeltchenko 
2923c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
2924c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
2925c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
2926c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
2927c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
29280a708f8fSGustavo F. Padovan 
29290a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
29300a708f8fSGustavo F. Padovan 							(unsigned long) &rfc);
29310a708f8fSGustavo F. Padovan 
2932f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
2933f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
2934f89cef09SAndrei Emeltchenko 
29358c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
29360a708f8fSGustavo F. Padovan 			break;
29370a708f8fSGustavo F. Padovan 
293847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_NONE ||
2939c1360a1cSGustavo F. Padovan 				test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
294047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
294147d1ec61SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
29420a708f8fSGustavo F. Padovan 		}
29430a708f8fSGustavo F. Padovan 		break;
29440a708f8fSGustavo F. Padovan 	}
29450a708f8fSGustavo F. Padovan 
2946fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
294759e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
29480a708f8fSGustavo F. Padovan 
29490a708f8fSGustavo F. Padovan 	return ptr - data;
29500a708f8fSGustavo F. Padovan }
29510a708f8fSGustavo F. Padovan 
295273ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
29530a708f8fSGustavo F. Padovan {
29540a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
29550a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
295673ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
295773ffa904SGustavo F. Padovan 	int len = chan->conf_len;
29580a708f8fSGustavo F. Padovan 	int type, hint, olen;
29590a708f8fSGustavo F. Padovan 	unsigned long val;
29600a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
296142dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
296242dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
29630a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
29640a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
2965c8f79162SAndrei Emeltchenko 	u16 size;
29660a708f8fSGustavo F. Padovan 
296773ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
29680a708f8fSGustavo F. Padovan 
29690a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
29700a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
29710a708f8fSGustavo F. Padovan 
29720a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
29730a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
29740a708f8fSGustavo F. Padovan 
29750a708f8fSGustavo F. Padovan 		switch (type) {
29760a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
29770a708f8fSGustavo F. Padovan 			mtu = val;
29780a708f8fSGustavo F. Padovan 			break;
29790a708f8fSGustavo F. Padovan 
29800a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
29810c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
29820a708f8fSGustavo F. Padovan 			break;
29830a708f8fSGustavo F. Padovan 
29840a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
29850a708f8fSGustavo F. Padovan 			break;
29860a708f8fSGustavo F. Padovan 
29870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
29880a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
29890a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
29900a708f8fSGustavo F. Padovan 			break;
29910a708f8fSGustavo F. Padovan 
29920a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
29930a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
2994c1360a1cSGustavo F. Padovan 				set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
299542dceae2SAndrei Emeltchenko 			break;
29960a708f8fSGustavo F. Padovan 
299742dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
299842dceae2SAndrei Emeltchenko 			remote_efs = 1;
299942dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
300042dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
30010a708f8fSGustavo F. Padovan 			break;
30020a708f8fSGustavo F. Padovan 
30036327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
30046327eb98SAndrei Emeltchenko 			if (!enable_hs)
30056327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
30066327eb98SAndrei Emeltchenko 
30076327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
30086327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3009836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
30106327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
30110a708f8fSGustavo F. Padovan 			break;
30120a708f8fSGustavo F. Padovan 
30130a708f8fSGustavo F. Padovan 		default:
30140a708f8fSGustavo F. Padovan 			if (hint)
30150a708f8fSGustavo F. Padovan 				break;
30160a708f8fSGustavo F. Padovan 
30170a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
30180a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
30190a708f8fSGustavo F. Padovan 			break;
30200a708f8fSGustavo F. Padovan 		}
30210a708f8fSGustavo F. Padovan 	}
30220a708f8fSGustavo F. Padovan 
302373ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
30240a708f8fSGustavo F. Padovan 		goto done;
30250a708f8fSGustavo F. Padovan 
30260c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
30270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
30280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3029c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
30300c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
30318c1d787bSGustavo F. Padovan 					chan->conn->feat_mask);
30320a708f8fSGustavo F. Padovan 			break;
30330a708f8fSGustavo F. Padovan 		}
30340a708f8fSGustavo F. Padovan 
303542dceae2SAndrei Emeltchenko 		if (remote_efs) {
303642dceae2SAndrei Emeltchenko 			if (__l2cap_efs_supported(chan))
303742dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
303842dceae2SAndrei Emeltchenko 			else
303942dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
304042dceae2SAndrei Emeltchenko 		}
304142dceae2SAndrei Emeltchenko 
30420c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
30430a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30440a708f8fSGustavo F. Padovan 
30450a708f8fSGustavo F. Padovan 		break;
30460a708f8fSGustavo F. Padovan 	}
30470a708f8fSGustavo F. Padovan 
30480a708f8fSGustavo F. Padovan done:
30490c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
30500a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
30510c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
30520a708f8fSGustavo F. Padovan 
305373ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
30540a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
30550a708f8fSGustavo F. Padovan 
30560a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
30570a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
30580a708f8fSGustavo F. Padovan 	}
30590a708f8fSGustavo F. Padovan 
30600a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
30610a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
30620a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
30630a708f8fSGustavo F. Padovan 
30640a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
30650a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
30660a708f8fSGustavo F. Padovan 		else {
30670c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3068c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
30690a708f8fSGustavo F. Padovan 		}
30700c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
30710a708f8fSGustavo F. Padovan 
307242dceae2SAndrei Emeltchenko 		if (remote_efs) {
307342dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
307442dceae2SAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
307542dceae2SAndrei Emeltchenko 					efs.stype != chan->local_stype) {
307642dceae2SAndrei Emeltchenko 
307742dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
307842dceae2SAndrei Emeltchenko 
307942dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
308042dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
308142dceae2SAndrei Emeltchenko 
308242dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
308342dceae2SAndrei Emeltchenko 							sizeof(efs),
308442dceae2SAndrei Emeltchenko 							(unsigned long) &efs);
30850e8b207eSAndrei Emeltchenko 			} else {
30863e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
30870e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
30880e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
308942dceae2SAndrei Emeltchenko 			}
309042dceae2SAndrei Emeltchenko 		}
309142dceae2SAndrei Emeltchenko 
30920a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
30930a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
309447d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3095c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
30960a708f8fSGustavo F. Padovan 			break;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
30996327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
31002c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
31016327eb98SAndrei Emeltchenko 			else
31026327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
31036327eb98SAndrei Emeltchenko 
31042c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
31050a708f8fSGustavo F. Padovan 
3106c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3107c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3108c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3109c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3110c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3111c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3112c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31130a708f8fSGustavo F. Padovan 
31140a708f8fSGustavo F. Padovan 			rfc.retrans_timeout =
31154fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
31160a708f8fSGustavo F. Padovan 			rfc.monitor_timeout =
31174fd21a88SAndrei Emeltchenko 				__constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
31180a708f8fSGustavo F. Padovan 
3119c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31200a708f8fSGustavo F. Padovan 
31210a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31220a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31230a708f8fSGustavo F. Padovan 
312442dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
312542dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
312642dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
312742dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
312842dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
312942dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
313042dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
313142dceae2SAndrei Emeltchenko 						le32_to_cpu(efs.acc_lat);
313242dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
313342dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
313442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
313542dceae2SAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
313642dceae2SAndrei Emeltchenko 			}
31370a708f8fSGustavo F. Padovan 			break;
31380a708f8fSGustavo F. Padovan 
31390a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3140c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
3141c8f79162SAndrei Emeltchenko 						chan->conn->mtu -
3142c8f79162SAndrei Emeltchenko 						L2CAP_EXT_HDR_SIZE -
3143c8f79162SAndrei Emeltchenko 						L2CAP_SDULEN_SIZE -
3144c8f79162SAndrei Emeltchenko 						L2CAP_FCS_SIZE);
3145c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3146c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
31470a708f8fSGustavo F. Padovan 
3148c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
31490a708f8fSGustavo F. Padovan 
31500a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
31510a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
31520a708f8fSGustavo F. Padovan 
31530a708f8fSGustavo F. Padovan 			break;
31540a708f8fSGustavo F. Padovan 
31550a708f8fSGustavo F. Padovan 		default:
31560a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
31570a708f8fSGustavo F. Padovan 
31580a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
31590c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
31600a708f8fSGustavo F. Padovan 		}
31610a708f8fSGustavo F. Padovan 
31620a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3163c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
31640a708f8fSGustavo F. Padovan 	}
3165fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
31660a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
316759e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
31680a708f8fSGustavo F. Padovan 
31690a708f8fSGustavo F. Padovan 	return ptr - data;
31700a708f8fSGustavo F. Padovan }
31710a708f8fSGustavo F. Padovan 
3172b4450035SGustavo F. Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
31730a708f8fSGustavo F. Padovan {
31740a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
31750a708f8fSGustavo F. Padovan 	void *ptr = req->data;
31760a708f8fSGustavo F. Padovan 	int type, olen;
31770a708f8fSGustavo F. Padovan 	unsigned long val;
317836e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
317966af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
31800a708f8fSGustavo F. Padovan 
3181fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
31820a708f8fSGustavo F. Padovan 
31830a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
31840a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
31850a708f8fSGustavo F. Padovan 
31860a708f8fSGustavo F. Padovan 		switch (type) {
31870a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
31880a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
31890a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
31900c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
31910a708f8fSGustavo F. Padovan 			} else
31920c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
31930c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
31940a708f8fSGustavo F. Padovan 			break;
31950a708f8fSGustavo F. Padovan 
31960a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
31970c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
31980a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
31990c1bc5c6SGustavo F. Padovan 							2, chan->flush_to);
32000a708f8fSGustavo F. Padovan 			break;
32010a708f8fSGustavo F. Padovan 
32020a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
32030a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
32040a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
32050a708f8fSGustavo F. Padovan 
3206c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
32070c1bc5c6SGustavo F. Padovan 							rfc.mode != chan->mode)
32080a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
32090a708f8fSGustavo F. Padovan 
321047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
32110a708f8fSGustavo F. Padovan 
32120a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
32130a708f8fSGustavo F. Padovan 					sizeof(rfc), (unsigned long) &rfc);
32140a708f8fSGustavo F. Padovan 			break;
32156327eb98SAndrei Emeltchenko 
32166327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
32176327eb98SAndrei Emeltchenko 			chan->tx_win = min_t(u16, val,
32186327eb98SAndrei Emeltchenko 						L2CAP_DEFAULT_EXT_WINDOW);
32193e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
32203e6b3b95SGustavo F. Padovan 							chan->tx_win);
32216327eb98SAndrei Emeltchenko 			break;
322266af7aafSAndrei Emeltchenko 
322366af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
322466af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
322566af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
322666af7aafSAndrei Emeltchenko 
322766af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
322866af7aafSAndrei Emeltchenko 					efs.stype != L2CAP_SERV_NOTRAFIC &&
322966af7aafSAndrei Emeltchenko 					efs.stype != chan->local_stype)
323066af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
323166af7aafSAndrei Emeltchenko 
323266af7aafSAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
323366af7aafSAndrei Emeltchenko 					sizeof(efs), (unsigned long) &efs);
323466af7aafSAndrei Emeltchenko 			break;
32350a708f8fSGustavo F. Padovan 		}
32360a708f8fSGustavo F. Padovan 	}
32370a708f8fSGustavo F. Padovan 
32380c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
32390a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
32400a708f8fSGustavo F. Padovan 
32410c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
32420a708f8fSGustavo F. Padovan 
32430e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
32440a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
32450a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
324647d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
324747d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
324847d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
324966af7aafSAndrei Emeltchenko 
325066af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
325166af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
325266af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
325366af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.sdu_itime);
325466af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
325566af7aafSAndrei Emeltchenko 				chan->local_flush_to =
325666af7aafSAndrei Emeltchenko 						le32_to_cpu(efs.flush_to);
325766af7aafSAndrei Emeltchenko 			}
32580a708f8fSGustavo F. Padovan 			break;
325966af7aafSAndrei Emeltchenko 
32600a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
326147d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
32620a708f8fSGustavo F. Padovan 		}
32630a708f8fSGustavo F. Padovan 	}
32640a708f8fSGustavo F. Padovan 
3265fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
326659e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
32670a708f8fSGustavo F. Padovan 
32680a708f8fSGustavo F. Padovan 	return ptr - data;
32690a708f8fSGustavo F. Padovan }
32700a708f8fSGustavo F. Padovan 
3271fe4128e0SGustavo F. Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
32720a708f8fSGustavo F. Padovan {
32730a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
32740a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
32750a708f8fSGustavo F. Padovan 
3276fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32770a708f8fSGustavo F. Padovan 
3278fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
32790a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
32800a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
32810a708f8fSGustavo F. Padovan 
32820a708f8fSGustavo F. Padovan 	return ptr - data;
32830a708f8fSGustavo F. Padovan }
32840a708f8fSGustavo F. Padovan 
32858c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3286710f9b0aSGustavo F. Padovan {
3287710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
32888c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3289710f9b0aSGustavo F. Padovan 	u8 buf[128];
3290710f9b0aSGustavo F. Padovan 
3291fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3292fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3293710f9b0aSGustavo F. Padovan 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3294710f9b0aSGustavo F. Padovan 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3295710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, chan->ident,
3296710f9b0aSGustavo F. Padovan 				L2CAP_CONN_RSP, sizeof(rsp), &rsp);
3297710f9b0aSGustavo F. Padovan 
3298c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3299710f9b0aSGustavo F. Padovan 		return;
3300710f9b0aSGustavo F. Padovan 
3301710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3302710f9b0aSGustavo F. Padovan 			l2cap_build_conf_req(chan, buf), buf);
3303710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3304710f9b0aSGustavo F. Padovan }
3305710f9b0aSGustavo F. Padovan 
330647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
33070a708f8fSGustavo F. Padovan {
33080a708f8fSGustavo F. Padovan 	int type, olen;
33090a708f8fSGustavo F. Padovan 	unsigned long val;
33100a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc;
33110a708f8fSGustavo F. Padovan 
331247d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
33130a708f8fSGustavo F. Padovan 
33140c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
33150a708f8fSGustavo F. Padovan 		return;
33160a708f8fSGustavo F. Padovan 
33170a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
33180a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
33190a708f8fSGustavo F. Padovan 
33200a708f8fSGustavo F. Padovan 		switch (type) {
33210a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
33220a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
33230a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
33240a708f8fSGustavo F. Padovan 			goto done;
33250a708f8fSGustavo F. Padovan 		}
33260a708f8fSGustavo F. Padovan 	}
33270a708f8fSGustavo F. Padovan 
332836e999a8SMat Martineau 	/* Use sane default values in case a misbehaving remote device
332936e999a8SMat Martineau 	 * did not send an RFC option.
333036e999a8SMat Martineau 	 */
333136e999a8SMat Martineau 	rfc.mode = chan->mode;
333236e999a8SMat Martineau 	rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
333336e999a8SMat Martineau 	rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
333436e999a8SMat Martineau 	rfc.max_pdu_size = cpu_to_le16(chan->imtu);
333536e999a8SMat Martineau 
333636e999a8SMat Martineau 	BT_ERR("Expected RFC option was not found, using defaults");
333736e999a8SMat Martineau 
33380a708f8fSGustavo F. Padovan done:
33390a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
33400a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
334147d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
334247d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
334347d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33440a708f8fSGustavo F. Padovan 		break;
33450a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
334647d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
33470a708f8fSGustavo F. Padovan 	}
33480a708f8fSGustavo F. Padovan }
33490a708f8fSGustavo F. Padovan 
33500a708f8fSGustavo F. Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33510a708f8fSGustavo F. Padovan {
3352e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
33530a708f8fSGustavo F. Padovan 
3354e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
33550a708f8fSGustavo F. Padovan 		return 0;
33560a708f8fSGustavo F. Padovan 
33570a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
33580a708f8fSGustavo F. Padovan 					cmd->ident == conn->info_ident) {
335917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
33600a708f8fSGustavo F. Padovan 
33610a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
33620a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
33630a708f8fSGustavo F. Padovan 
33640a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
33650a708f8fSGustavo F. Padovan 	}
33660a708f8fSGustavo F. Padovan 
33670a708f8fSGustavo F. Padovan 	return 0;
33680a708f8fSGustavo F. Padovan }
33690a708f8fSGustavo F. Padovan 
33700a708f8fSGustavo F. Padovan static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
33710a708f8fSGustavo F. Padovan {
33720a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
33730a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
337423691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
33750a708f8fSGustavo F. Padovan 	struct sock *parent, *sk = NULL;
33760a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
33770a708f8fSGustavo F. Padovan 
33780a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
33790a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
33800a708f8fSGustavo F. Padovan 
3381097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
33820a708f8fSGustavo F. Padovan 
33830a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
3384c2287681SIdo Yariv 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst);
338523691d75SGustavo F. Padovan 	if (!pchan) {
33860a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
33870a708f8fSGustavo F. Padovan 		goto sendresp;
33880a708f8fSGustavo F. Padovan 	}
33890a708f8fSGustavo F. Padovan 
339023691d75SGustavo F. Padovan 	parent = pchan->sk;
339123691d75SGustavo F. Padovan 
33923df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
3393aa2ac881SGustavo F. Padovan 	lock_sock(parent);
33940a708f8fSGustavo F. Padovan 
33950a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
33960a708f8fSGustavo F. Padovan 	if (psm != cpu_to_le16(0x0001) &&
33970a708f8fSGustavo F. Padovan 				!hci_conn_check_link_mode(conn->hcon)) {
33989f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
33990a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
34000a708f8fSGustavo F. Padovan 		goto response;
34010a708f8fSGustavo F. Padovan 	}
34020a708f8fSGustavo F. Padovan 
34030a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
34040a708f8fSGustavo F. Padovan 
34050a708f8fSGustavo F. Padovan 	/* Check for backlog size */
34060a708f8fSGustavo F. Padovan 	if (sk_acceptq_is_full(parent)) {
34070a708f8fSGustavo F. Padovan 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
34080a708f8fSGustavo F. Padovan 		goto response;
34090a708f8fSGustavo F. Padovan 	}
34100a708f8fSGustavo F. Padovan 
341180808e43SGustavo F. Padovan 	chan = pchan->ops->new_connection(pchan->data);
341280808e43SGustavo F. Padovan 	if (!chan)
34130a708f8fSGustavo F. Padovan 		goto response;
34140a708f8fSGustavo F. Padovan 
341580808e43SGustavo F. Padovan 	sk = chan->sk;
341680808e43SGustavo F. Padovan 
34170a708f8fSGustavo F. Padovan 	/* Check if we already have channel with that dcid */
3418baa7e1faSGustavo F. Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
34190a708f8fSGustavo F. Padovan 		sock_set_flag(sk, SOCK_ZAPPED);
3420ba3bd0eeSGustavo F. Padovan 		chan->ops->close(chan->data);
34210a708f8fSGustavo F. Padovan 		goto response;
34220a708f8fSGustavo F. Padovan 	}
34230a708f8fSGustavo F. Padovan 
34240a708f8fSGustavo F. Padovan 	hci_conn_hold(conn->hcon);
34250a708f8fSGustavo F. Padovan 
34260a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->src, conn->src);
34270a708f8fSGustavo F. Padovan 	bacpy(&bt_sk(sk)->dst, conn->dst);
3428fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
3429fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
34300a708f8fSGustavo F. Padovan 
3431d1010240SGustavo F. Padovan 	bt_accept_enqueue(parent, sk);
3432d1010240SGustavo F. Padovan 
34336be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
343448454079SGustavo F. Padovan 
3435fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
34360a708f8fSGustavo F. Padovan 
3437c9b66675SGustavo F. Padovan 	__set_chan_timer(chan, sk->sk_sndtimeo);
34380a708f8fSGustavo F. Padovan 
3439fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
34400a708f8fSGustavo F. Padovan 
34410a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
3442d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
3443c5daa683SGustavo Padovan 			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
34440e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONNECT2);
34450a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
34460a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
34470a708f8fSGustavo F. Padovan 				parent->sk_data_ready(parent, 0);
34480a708f8fSGustavo F. Padovan 			} else {
34490e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_CONFIG);
34500a708f8fSGustavo F. Padovan 				result = L2CAP_CR_SUCCESS;
34510a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
34520a708f8fSGustavo F. Padovan 			}
34530a708f8fSGustavo F. Padovan 		} else {
34540e587be7SAndrei Emeltchenko 			__l2cap_state_change(chan, BT_CONNECT2);
34550a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
34560a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
34570a708f8fSGustavo F. Padovan 		}
34580a708f8fSGustavo F. Padovan 	} else {
34590e587be7SAndrei Emeltchenko 		__l2cap_state_change(chan, BT_CONNECT2);
34600a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
34610a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
34620a708f8fSGustavo F. Padovan 	}
34630a708f8fSGustavo F. Padovan 
34640a708f8fSGustavo F. Padovan response:
3465aa2ac881SGustavo F. Padovan 	release_sock(parent);
34663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
34670a708f8fSGustavo F. Padovan 
34680a708f8fSGustavo F. Padovan sendresp:
34690a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
34700a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
34710a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
34720a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
34730a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
34740a708f8fSGustavo F. Padovan 
34750a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
34760a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
34770a708f8fSGustavo F. Padovan 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
34780a708f8fSGustavo F. Padovan 
34790a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
34800a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
34810a708f8fSGustavo F. Padovan 
3482ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
34830a708f8fSGustavo F. Padovan 
34840a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, conn->info_ident,
34850a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(info), &info);
34860a708f8fSGustavo F. Padovan 	}
34870a708f8fSGustavo F. Padovan 
3488c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
34890a708f8fSGustavo F. Padovan 				result == L2CAP_CR_SUCCESS) {
34900a708f8fSGustavo F. Padovan 		u8 buf[128];
3491c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
34920a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
349373ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
349473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
34950a708f8fSGustavo F. Padovan 	}
34960a708f8fSGustavo F. Padovan 
34970a708f8fSGustavo F. Padovan 	return 0;
34980a708f8fSGustavo F. Padovan }
34990a708f8fSGustavo F. Padovan 
35000a708f8fSGustavo F. Padovan static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
35010a708f8fSGustavo F. Padovan {
35020a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
35030a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
350448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35050a708f8fSGustavo F. Padovan 	u8 req[128];
35063df91ea2SAndrei Emeltchenko 	int err;
35070a708f8fSGustavo F. Padovan 
35080a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
35090a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
35100a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
35110a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
35120a708f8fSGustavo F. Padovan 
35131b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
35141b009c98SAndrei Emeltchenko 						dcid, scid, result, status);
35150a708f8fSGustavo F. Padovan 
35163df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
35173df91ea2SAndrei Emeltchenko 
35180a708f8fSGustavo F. Padovan 	if (scid) {
35193df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
35203df91ea2SAndrei Emeltchenko 		if (!chan) {
35213df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35223df91ea2SAndrei Emeltchenko 			goto unlock;
35233df91ea2SAndrei Emeltchenko 		}
35240a708f8fSGustavo F. Padovan 	} else {
35253df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
35263df91ea2SAndrei Emeltchenko 		if (!chan) {
35273df91ea2SAndrei Emeltchenko 			err = -EFAULT;
35283df91ea2SAndrei Emeltchenko 			goto unlock;
35293df91ea2SAndrei Emeltchenko 		}
35300a708f8fSGustavo F. Padovan 	}
35310a708f8fSGustavo F. Padovan 
35323df91ea2SAndrei Emeltchenko 	err = 0;
35333df91ea2SAndrei Emeltchenko 
35346be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
353548454079SGustavo F. Padovan 
35360a708f8fSGustavo F. Padovan 	switch (result) {
35370a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
353889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
3539fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
3540fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
3541c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
35420a708f8fSGustavo F. Padovan 
3543c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
35440a708f8fSGustavo F. Padovan 			break;
35450a708f8fSGustavo F. Padovan 
35460a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
354773ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, req), req);
354873ffa904SGustavo F. Padovan 		chan->num_conf_req++;
35490a708f8fSGustavo F. Padovan 		break;
35500a708f8fSGustavo F. Padovan 
35510a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
3552c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
35530a708f8fSGustavo F. Padovan 		break;
35540a708f8fSGustavo F. Padovan 
35550a708f8fSGustavo F. Padovan 	default:
355648454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
35570a708f8fSGustavo F. Padovan 		break;
35580a708f8fSGustavo F. Padovan 	}
35590a708f8fSGustavo F. Padovan 
35606be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
35613df91ea2SAndrei Emeltchenko 
35623df91ea2SAndrei Emeltchenko unlock:
35633df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
35643df91ea2SAndrei Emeltchenko 
35653df91ea2SAndrei Emeltchenko 	return err;
35660a708f8fSGustavo F. Padovan }
35670a708f8fSGustavo F. Padovan 
356847d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
35690a708f8fSGustavo F. Padovan {
35700a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
35710a708f8fSGustavo F. Padovan 	 * sides request it.
35720a708f8fSGustavo F. Padovan 	 */
35730c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
357447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
3575c1360a1cSGustavo F. Padovan 	else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
357647d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
35770a708f8fSGustavo F. Padovan }
35780a708f8fSGustavo F. Padovan 
35790a708f8fSGustavo F. Padovan static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
35800a708f8fSGustavo F. Padovan {
35810a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
35820a708f8fSGustavo F. Padovan 	u16 dcid, flags;
35830a708f8fSGustavo F. Padovan 	u8 rsp[64];
358448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
35853c588192SMat Martineau 	int len, err = 0;
35860a708f8fSGustavo F. Padovan 
35870a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
35880a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
35890a708f8fSGustavo F. Padovan 
35900a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
35910a708f8fSGustavo F. Padovan 
3592baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
359348454079SGustavo F. Padovan 	if (!chan)
35940a708f8fSGustavo F. Padovan 		return -ENOENT;
35950a708f8fSGustavo F. Padovan 
3596033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
3597e2fd318eSIlia Kolomisnky 		struct l2cap_cmd_rej_cid rej;
35980a708f8fSGustavo F. Padovan 
3599e2fd318eSIlia Kolomisnky 		rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
3600e2fd318eSIlia Kolomisnky 		rej.scid = cpu_to_le16(chan->scid);
3601e2fd318eSIlia Kolomisnky 		rej.dcid = cpu_to_le16(chan->dcid);
3602e2fd318eSIlia Kolomisnky 
36030a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
36040a708f8fSGustavo F. Padovan 				sizeof(rej), &rej);
36050a708f8fSGustavo F. Padovan 		goto unlock;
36060a708f8fSGustavo F. Padovan 	}
36070a708f8fSGustavo F. Padovan 
36080a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
36090a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
36107ac28817SDan Rosenberg 	if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
36110a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3612fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36130a708f8fSGustavo F. Padovan 					L2CAP_CONF_REJECT, flags), rsp);
36140a708f8fSGustavo F. Padovan 		goto unlock;
36150a708f8fSGustavo F. Padovan 	}
36160a708f8fSGustavo F. Padovan 
36170a708f8fSGustavo F. Padovan 	/* Store config. */
361873ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
361973ffa904SGustavo F. Padovan 	chan->conf_len += len;
36200a708f8fSGustavo F. Padovan 
362159e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
36220a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
36230a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
3624fe4128e0SGustavo F. Padovan 				l2cap_build_conf_rsp(chan, rsp,
36255325e5bbSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, flags), rsp);
36260a708f8fSGustavo F. Padovan 		goto unlock;
36270a708f8fSGustavo F. Padovan 	}
36280a708f8fSGustavo F. Padovan 
36290a708f8fSGustavo F. Padovan 	/* Complete config. */
363073ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
36310a708f8fSGustavo F. Padovan 	if (len < 0) {
3632e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
36330a708f8fSGustavo F. Padovan 		goto unlock;
36340a708f8fSGustavo F. Padovan 	}
36350a708f8fSGustavo F. Padovan 
36360a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
363773ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
36380a708f8fSGustavo F. Padovan 
36390a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
364073ffa904SGustavo F. Padovan 	chan->conf_len = 0;
36410a708f8fSGustavo F. Padovan 
3642c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
36430a708f8fSGustavo F. Padovan 		goto unlock;
36440a708f8fSGustavo F. Padovan 
3645c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
364647d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
36470a708f8fSGustavo F. Padovan 
364889bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
36490a708f8fSGustavo F. Padovan 
3650105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3651105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
36523c588192SMat Martineau 			err = l2cap_ertm_init(chan);
36530a708f8fSGustavo F. Padovan 
36543c588192SMat Martineau 		if (err < 0)
36553c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
36563c588192SMat Martineau 		else
3657cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
36583c588192SMat Martineau 
36590a708f8fSGustavo F. Padovan 		goto unlock;
36600a708f8fSGustavo F. Padovan 	}
36610a708f8fSGustavo F. Padovan 
3662c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
36630a708f8fSGustavo F. Padovan 		u8 buf[64];
36640a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
366573ffa904SGustavo F. Padovan 					l2cap_build_conf_req(chan, buf), buf);
366673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
36670a708f8fSGustavo F. Padovan 	}
36680a708f8fSGustavo F. Padovan 
36690e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
36700e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
36710e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
36720e8b207eSAndrei Emeltchenko 			test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
36730e8b207eSAndrei Emeltchenko 
36740e8b207eSAndrei Emeltchenko 		/* check compatibility */
36750e8b207eSAndrei Emeltchenko 
36760e8b207eSAndrei Emeltchenko 		clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
36770e8b207eSAndrei Emeltchenko 		set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
36780e8b207eSAndrei Emeltchenko 
36790e8b207eSAndrei Emeltchenko 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
36800e8b207eSAndrei Emeltchenko 					l2cap_build_conf_rsp(chan, rsp,
36815325e5bbSAndrei Emeltchenko 					L2CAP_CONF_SUCCESS, flags), rsp);
36820e8b207eSAndrei Emeltchenko 	}
36830e8b207eSAndrei Emeltchenko 
36840a708f8fSGustavo F. Padovan unlock:
36856be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
36863c588192SMat Martineau 	return err;
36870a708f8fSGustavo F. Padovan }
36880a708f8fSGustavo F. Padovan 
36890a708f8fSGustavo F. Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
36900a708f8fSGustavo F. Padovan {
36910a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
36920a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
369348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
369461386cbaSAndrei Emeltchenko 	int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
36953c588192SMat Martineau 	int err = 0;
36960a708f8fSGustavo F. Padovan 
36970a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
36980a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
36990a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
37000a708f8fSGustavo F. Padovan 
370161386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
370261386cbaSAndrei Emeltchenko 	       result, len);
37030a708f8fSGustavo F. Padovan 
3704baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
370548454079SGustavo F. Padovan 	if (!chan)
37060a708f8fSGustavo F. Padovan 		return 0;
37070a708f8fSGustavo F. Padovan 
37080a708f8fSGustavo F. Padovan 	switch (result) {
37090a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
371047d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
37110e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
37120a708f8fSGustavo F. Padovan 		break;
37130a708f8fSGustavo F. Padovan 
37140e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
37150e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
37160e8b207eSAndrei Emeltchenko 
37170e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
37180e8b207eSAndrei Emeltchenko 			char buf[64];
37190e8b207eSAndrei Emeltchenko 
37200e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
37210e8b207eSAndrei Emeltchenko 								buf, &result);
37220e8b207eSAndrei Emeltchenko 			if (len < 0) {
37230e8b207eSAndrei Emeltchenko 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37240e8b207eSAndrei Emeltchenko 				goto done;
37250e8b207eSAndrei Emeltchenko 			}
37260e8b207eSAndrei Emeltchenko 
37270e8b207eSAndrei Emeltchenko 			/* check compatibility */
37280e8b207eSAndrei Emeltchenko 
37290e8b207eSAndrei Emeltchenko 			clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
37300e8b207eSAndrei Emeltchenko 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37310e8b207eSAndrei Emeltchenko 
37320e8b207eSAndrei Emeltchenko 			l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
37330e8b207eSAndrei Emeltchenko 						l2cap_build_conf_rsp(chan, buf,
37340e8b207eSAndrei Emeltchenko 						L2CAP_CONF_SUCCESS, 0x0000), buf);
37350e8b207eSAndrei Emeltchenko 		}
37360e8b207eSAndrei Emeltchenko 		goto done;
37370e8b207eSAndrei Emeltchenko 
37380a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
373973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
37400a708f8fSGustavo F. Padovan 			char req[64];
37410a708f8fSGustavo F. Padovan 
37420a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
3743e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37440a708f8fSGustavo F. Padovan 				goto done;
37450a708f8fSGustavo F. Padovan 			}
37460a708f8fSGustavo F. Padovan 
37470a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
37480a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
3749b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
3750b4450035SGustavo F. Padovan 								req, &result);
37510a708f8fSGustavo F. Padovan 			if (len < 0) {
3752e92c8e70SGustavo F. Padovan 				l2cap_send_disconn_req(conn, chan, ECONNRESET);
37530a708f8fSGustavo F. Padovan 				goto done;
37540a708f8fSGustavo F. Padovan 			}
37550a708f8fSGustavo F. Padovan 
37560a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
37570a708f8fSGustavo F. Padovan 						L2CAP_CONF_REQ, len, req);
375873ffa904SGustavo F. Padovan 			chan->num_conf_req++;
37590a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
37600a708f8fSGustavo F. Padovan 				goto done;
37610a708f8fSGustavo F. Padovan 			break;
37620a708f8fSGustavo F. Padovan 		}
37630a708f8fSGustavo F. Padovan 
37640a708f8fSGustavo F. Padovan 	default:
37656be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
37662e0052e4SAndrei Emeltchenko 
3767ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
3768e92c8e70SGustavo F. Padovan 		l2cap_send_disconn_req(conn, chan, ECONNRESET);
37690a708f8fSGustavo F. Padovan 		goto done;
37700a708f8fSGustavo F. Padovan 	}
37710a708f8fSGustavo F. Padovan 
377259e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
37730a708f8fSGustavo F. Padovan 		goto done;
37740a708f8fSGustavo F. Padovan 
3775c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
37760a708f8fSGustavo F. Padovan 
3777c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
377847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
37790a708f8fSGustavo F. Padovan 
378089bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONNECTED);
3781105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
3782105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
37833c588192SMat Martineau 			err = l2cap_ertm_init(chan);
37840a708f8fSGustavo F. Padovan 
37853c588192SMat Martineau 		if (err < 0)
37863c588192SMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, -err);
37873c588192SMat Martineau 		else
3788cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
37890a708f8fSGustavo F. Padovan 	}
37900a708f8fSGustavo F. Padovan 
37910a708f8fSGustavo F. Padovan done:
37926be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
37933c588192SMat Martineau 	return err;
37940a708f8fSGustavo F. Padovan }
37950a708f8fSGustavo F. Padovan 
37960a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
37970a708f8fSGustavo F. Padovan {
37980a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
37990a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
38000a708f8fSGustavo F. Padovan 	u16 dcid, scid;
380148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38020a708f8fSGustavo F. Padovan 	struct sock *sk;
38030a708f8fSGustavo F. Padovan 
38040a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
38050a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
38060a708f8fSGustavo F. Padovan 
38070a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
38080a708f8fSGustavo F. Padovan 
38093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38103df91ea2SAndrei Emeltchenko 
38113df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
38123df91ea2SAndrei Emeltchenko 	if (!chan) {
38133df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38140a708f8fSGustavo F. Padovan 		return 0;
38153df91ea2SAndrei Emeltchenko 	}
38160a708f8fSGustavo F. Padovan 
38176be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
38186be36555SAndrei Emeltchenko 
381948454079SGustavo F. Padovan 	sk = chan->sk;
382048454079SGustavo F. Padovan 
3821fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
3822fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
38230a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
38240a708f8fSGustavo F. Padovan 
38256be36555SAndrei Emeltchenko 	lock_sock(sk);
38260a708f8fSGustavo F. Padovan 	sk->sk_shutdown = SHUTDOWN_MASK;
38276be36555SAndrei Emeltchenko 	release_sock(sk);
38280a708f8fSGustavo F. Padovan 
382961d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
383048454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
38316be36555SAndrei Emeltchenko 
38326be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38330a708f8fSGustavo F. Padovan 
3834ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
383561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38363df91ea2SAndrei Emeltchenko 
38373df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38383df91ea2SAndrei Emeltchenko 
38390a708f8fSGustavo F. Padovan 	return 0;
38400a708f8fSGustavo F. Padovan }
38410a708f8fSGustavo F. Padovan 
38420a708f8fSGustavo F. Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38430a708f8fSGustavo F. Padovan {
38440a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
38450a708f8fSGustavo F. Padovan 	u16 dcid, scid;
384648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
38470a708f8fSGustavo F. Padovan 
38480a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
38490a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
38500a708f8fSGustavo F. Padovan 
38510a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
38520a708f8fSGustavo F. Padovan 
38533df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
38543df91ea2SAndrei Emeltchenko 
38553df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
38563df91ea2SAndrei Emeltchenko 	if (!chan) {
38573df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
38580a708f8fSGustavo F. Padovan 		return 0;
38593df91ea2SAndrei Emeltchenko 	}
38600a708f8fSGustavo F. Padovan 
38616be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
386248454079SGustavo F. Padovan 
386361d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
386448454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
38656be36555SAndrei Emeltchenko 
38666be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
38670a708f8fSGustavo F. Padovan 
3868ba3bd0eeSGustavo F. Padovan 	chan->ops->close(chan->data);
386961d6ef3eSMat Martineau 	l2cap_chan_put(chan);
38703df91ea2SAndrei Emeltchenko 
38713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
38723df91ea2SAndrei Emeltchenko 
38730a708f8fSGustavo F. Padovan 	return 0;
38740a708f8fSGustavo F. Padovan }
38750a708f8fSGustavo F. Padovan 
38760a708f8fSGustavo F. Padovan static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
38770a708f8fSGustavo F. Padovan {
38780a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
38790a708f8fSGustavo F. Padovan 	u16 type;
38800a708f8fSGustavo F. Padovan 
38810a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
38820a708f8fSGustavo F. Padovan 
38830a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
38840a708f8fSGustavo F. Padovan 
38850a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
38860a708f8fSGustavo F. Padovan 		u8 buf[8];
38870a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
38880a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
38890a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
38900a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
38910a708f8fSGustavo F. Padovan 		if (!disable_ertm)
38920a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
38930a708f8fSGustavo F. Padovan 							 | L2CAP_FEAT_FCS;
3894a5fd6f30SAndrei Emeltchenko 		if (enable_hs)
38956327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
38966327eb98SAndrei Emeltchenko 						| L2CAP_FEAT_EXT_WINDOW;
3897a5fd6f30SAndrei Emeltchenko 
38980a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
38990a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39000a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
39010a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
39020a708f8fSGustavo F. Padovan 		u8 buf[12];
39030a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
390450a147cdSMat Martineau 
390550a147cdSMat Martineau 		if (enable_hs)
390650a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
390750a147cdSMat Martineau 		else
390850a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
390950a147cdSMat Martineau 
39100a708f8fSGustavo F. Padovan 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39110a708f8fSGustavo F. Padovan 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
3912c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
39130a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39140a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(buf), buf);
39150a708f8fSGustavo F. Padovan 	} else {
39160a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
39170a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
39180a708f8fSGustavo F. Padovan 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
39190a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident,
39200a708f8fSGustavo F. Padovan 					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
39210a708f8fSGustavo F. Padovan 	}
39220a708f8fSGustavo F. Padovan 
39230a708f8fSGustavo F. Padovan 	return 0;
39240a708f8fSGustavo F. Padovan }
39250a708f8fSGustavo F. Padovan 
39260a708f8fSGustavo F. Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
39270a708f8fSGustavo F. Padovan {
39280a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
39290a708f8fSGustavo F. Padovan 	u16 type, result;
39300a708f8fSGustavo F. Padovan 
39310a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
39320a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
39330a708f8fSGustavo F. Padovan 
39340a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
39350a708f8fSGustavo F. Padovan 
3936e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
3937e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
3938e90165beSAndrei Emeltchenko 			conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
3939e90165beSAndrei Emeltchenko 		return 0;
3940e90165beSAndrei Emeltchenko 
394117cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
39420a708f8fSGustavo F. Padovan 
39430a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
39440a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39450a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39460a708f8fSGustavo F. Padovan 
39470a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39480a708f8fSGustavo F. Padovan 
39490a708f8fSGustavo F. Padovan 		return 0;
39500a708f8fSGustavo F. Padovan 	}
39510a708f8fSGustavo F. Padovan 
3952978c93b9SAndrei Emeltchenko 	switch (type) {
3953978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
39540a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
39550a708f8fSGustavo F. Padovan 
39560a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
39570a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
39580a708f8fSGustavo F. Padovan 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
39590a708f8fSGustavo F. Padovan 
39600a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
39610a708f8fSGustavo F. Padovan 
39620a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
39630a708f8fSGustavo F. Padovan 					L2CAP_INFO_REQ, sizeof(req), &req);
39640a708f8fSGustavo F. Padovan 		} else {
39650a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39660a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
39670a708f8fSGustavo F. Padovan 
39680a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
39690a708f8fSGustavo F. Padovan 		}
3970978c93b9SAndrei Emeltchenko 		break;
3971978c93b9SAndrei Emeltchenko 
3972978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
3973978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
39740a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39750a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39760a708f8fSGustavo F. Padovan 
39770a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
3978978c93b9SAndrei Emeltchenko 		break;
39790a708f8fSGustavo F. Padovan 	}
39800a708f8fSGustavo F. Padovan 
39810a708f8fSGustavo F. Padovan 	return 0;
39820a708f8fSGustavo F. Padovan }
39830a708f8fSGustavo F. Padovan 
3984f94ff6ffSMat Martineau static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
3985f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3986f94ff6ffSMat Martineau 					void *data)
3987f94ff6ffSMat Martineau {
3988f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
3989f94ff6ffSMat Martineau 	struct l2cap_create_chan_rsp rsp;
3990f94ff6ffSMat Martineau 	u16 psm, scid;
3991f94ff6ffSMat Martineau 
3992f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
3993f94ff6ffSMat Martineau 		return -EPROTO;
3994f94ff6ffSMat Martineau 
3995f94ff6ffSMat Martineau 	if (!enable_hs)
3996f94ff6ffSMat Martineau 		return -EINVAL;
3997f94ff6ffSMat Martineau 
3998f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
3999f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4000f94ff6ffSMat Martineau 
4001f94ff6ffSMat Martineau 	BT_DBG("psm %d, scid %d, amp_id %d", psm, scid, req->amp_id);
4002f94ff6ffSMat Martineau 
4003f94ff6ffSMat Martineau 	/* Placeholder: Always reject */
4004f94ff6ffSMat Martineau 	rsp.dcid = 0;
4005f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
40068ce0c498SAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
40078ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4008f94ff6ffSMat Martineau 
4009f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4010f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4011f94ff6ffSMat Martineau 
4012f94ff6ffSMat Martineau 	return 0;
4013f94ff6ffSMat Martineau }
4014f94ff6ffSMat Martineau 
4015f94ff6ffSMat Martineau static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
4016f94ff6ffSMat Martineau 					struct l2cap_cmd_hdr *cmd, void *data)
4017f94ff6ffSMat Martineau {
4018f94ff6ffSMat Martineau 	BT_DBG("conn %p", conn);
4019f94ff6ffSMat Martineau 
4020f94ff6ffSMat Martineau 	return l2cap_connect_rsp(conn, cmd, data);
4021f94ff6ffSMat Martineau }
4022f94ff6ffSMat Martineau 
40238d5a04a1SMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
40248d5a04a1SMat Martineau 							u16 icid, u16 result)
40258d5a04a1SMat Martineau {
40268d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
40278d5a04a1SMat Martineau 
40288d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40298d5a04a1SMat Martineau 
40308d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40318d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
40328d5a04a1SMat Martineau 
40338d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_RSP, sizeof(rsp), &rsp);
40348d5a04a1SMat Martineau }
40358d5a04a1SMat Martineau 
40368d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_conn *conn,
40378d5a04a1SMat Martineau 				struct l2cap_chan *chan, u16 icid, u16 result)
40388d5a04a1SMat Martineau {
40398d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
40408d5a04a1SMat Martineau 	u8 ident;
40418d5a04a1SMat Martineau 
40428d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
40438d5a04a1SMat Martineau 
40448d5a04a1SMat Martineau 	ident = l2cap_get_ident(conn);
40458d5a04a1SMat Martineau 	if (chan)
40468d5a04a1SMat Martineau 		chan->ident = ident;
40478d5a04a1SMat Martineau 
40488d5a04a1SMat Martineau 	cfm.icid = cpu_to_le16(icid);
40498d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
40508d5a04a1SMat Martineau 
40518d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM, sizeof(cfm), &cfm);
40528d5a04a1SMat Martineau }
40538d5a04a1SMat Martineau 
40548d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
40558d5a04a1SMat Martineau 								u16 icid)
40568d5a04a1SMat Martineau {
40578d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
40588d5a04a1SMat Martineau 
40598d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
40608d5a04a1SMat Martineau 
40618d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
40628d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
40638d5a04a1SMat Martineau }
40648d5a04a1SMat Martineau 
40658d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
40668d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40678d5a04a1SMat Martineau {
40688d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
40698d5a04a1SMat Martineau 	u16 icid = 0;
40708d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
40718d5a04a1SMat Martineau 
40728d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
40738d5a04a1SMat Martineau 		return -EPROTO;
40748d5a04a1SMat Martineau 
40758d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
40768d5a04a1SMat Martineau 
40778d5a04a1SMat Martineau 	BT_DBG("icid %d, dest_amp_id %d", icid, req->dest_amp_id);
40788d5a04a1SMat Martineau 
40798d5a04a1SMat Martineau 	if (!enable_hs)
40808d5a04a1SMat Martineau 		return -EINVAL;
40818d5a04a1SMat Martineau 
40828d5a04a1SMat Martineau 	/* Placeholder: Always refuse */
40838d5a04a1SMat Martineau 	l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
40848d5a04a1SMat Martineau 
40858d5a04a1SMat Martineau 	return 0;
40868d5a04a1SMat Martineau }
40878d5a04a1SMat Martineau 
40888d5a04a1SMat Martineau static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
40898d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
40908d5a04a1SMat Martineau {
40918d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
40928d5a04a1SMat Martineau 	u16 icid, result;
40938d5a04a1SMat Martineau 
40948d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
40958d5a04a1SMat Martineau 		return -EPROTO;
40968d5a04a1SMat Martineau 
40978d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
40988d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
40998d5a04a1SMat Martineau 
41008d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
41018d5a04a1SMat Martineau 
41028d5a04a1SMat Martineau 	/* Placeholder: Always unconfirmed */
41038d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm(conn, NULL, icid, L2CAP_MC_UNCONFIRMED);
41048d5a04a1SMat Martineau 
41058d5a04a1SMat Martineau 	return 0;
41068d5a04a1SMat Martineau }
41078d5a04a1SMat Martineau 
41088d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm(struct l2cap_conn *conn,
41098d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
41108d5a04a1SMat Martineau {
41118d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
41128d5a04a1SMat Martineau 	u16 icid, result;
41138d5a04a1SMat Martineau 
41148d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
41158d5a04a1SMat Martineau 		return -EPROTO;
41168d5a04a1SMat Martineau 
41178d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
41188d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
41198d5a04a1SMat Martineau 
41208d5a04a1SMat Martineau 	BT_DBG("icid %d, result %d", icid, result);
41218d5a04a1SMat Martineau 
41228d5a04a1SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
41238d5a04a1SMat Martineau 
41248d5a04a1SMat Martineau 	return 0;
41258d5a04a1SMat Martineau }
41268d5a04a1SMat Martineau 
41278d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
41288d5a04a1SMat Martineau 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, void *data)
41298d5a04a1SMat Martineau {
41308d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
41318d5a04a1SMat Martineau 	u16 icid;
41328d5a04a1SMat Martineau 
41338d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
41348d5a04a1SMat Martineau 		return -EPROTO;
41358d5a04a1SMat Martineau 
41368d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
41378d5a04a1SMat Martineau 
41388d5a04a1SMat Martineau 	BT_DBG("icid %d", icid);
41398d5a04a1SMat Martineau 
41408d5a04a1SMat Martineau 	return 0;
41418d5a04a1SMat Martineau }
41428d5a04a1SMat Martineau 
4143e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
4144de73115aSClaudio Takahasi 							u16 to_multiplier)
4145de73115aSClaudio Takahasi {
4146de73115aSClaudio Takahasi 	u16 max_latency;
4147de73115aSClaudio Takahasi 
4148de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
4149de73115aSClaudio Takahasi 		return -EINVAL;
4150de73115aSClaudio Takahasi 
4151de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
4152de73115aSClaudio Takahasi 		return -EINVAL;
4153de73115aSClaudio Takahasi 
4154de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
4155de73115aSClaudio Takahasi 		return -EINVAL;
4156de73115aSClaudio Takahasi 
4157de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
4158de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
4159de73115aSClaudio Takahasi 		return -EINVAL;
4160de73115aSClaudio Takahasi 
4161de73115aSClaudio Takahasi 	return 0;
4162de73115aSClaudio Takahasi }
4163de73115aSClaudio Takahasi 
4164de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
4165de73115aSClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
4166de73115aSClaudio Takahasi {
4167de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
4168de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
4169de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
4170de73115aSClaudio Takahasi 	u16 min, max, latency, to_multiplier, cmd_len;
41712ce603ebSClaudio Takahasi 	int err;
4172de73115aSClaudio Takahasi 
4173de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
4174de73115aSClaudio Takahasi 		return -EINVAL;
4175de73115aSClaudio Takahasi 
4176de73115aSClaudio Takahasi 	cmd_len = __le16_to_cpu(cmd->len);
4177de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
4178de73115aSClaudio Takahasi 		return -EPROTO;
4179de73115aSClaudio Takahasi 
4180de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
4181de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
4182de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
4183de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
4184de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
4185de73115aSClaudio Takahasi 
4186de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
4187de73115aSClaudio Takahasi 						min, max, latency, to_multiplier);
4188de73115aSClaudio Takahasi 
4189de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
41902ce603ebSClaudio Takahasi 
41912ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
41922ce603ebSClaudio Takahasi 	if (err)
4193de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
4194de73115aSClaudio Takahasi 	else
4195de73115aSClaudio Takahasi 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
4196de73115aSClaudio Takahasi 
4197de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
4198de73115aSClaudio Takahasi 							sizeof(rsp), &rsp);
4199de73115aSClaudio Takahasi 
42002ce603ebSClaudio Takahasi 	if (!err)
42012ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
42022ce603ebSClaudio Takahasi 
4203de73115aSClaudio Takahasi 	return 0;
4204de73115aSClaudio Takahasi }
4205de73115aSClaudio Takahasi 
42063300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
42073300d9a9SClaudio Takahasi 			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
42083300d9a9SClaudio Takahasi {
42093300d9a9SClaudio Takahasi 	int err = 0;
42103300d9a9SClaudio Takahasi 
42113300d9a9SClaudio Takahasi 	switch (cmd->code) {
42123300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
42133300d9a9SClaudio Takahasi 		l2cap_command_rej(conn, cmd, data);
42143300d9a9SClaudio Takahasi 		break;
42153300d9a9SClaudio Takahasi 
42163300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
42173300d9a9SClaudio Takahasi 		err = l2cap_connect_req(conn, cmd, data);
42183300d9a9SClaudio Takahasi 		break;
42193300d9a9SClaudio Takahasi 
42203300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
42213300d9a9SClaudio Takahasi 		err = l2cap_connect_rsp(conn, cmd, data);
42223300d9a9SClaudio Takahasi 		break;
42233300d9a9SClaudio Takahasi 
42243300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
42253300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
42263300d9a9SClaudio Takahasi 		break;
42273300d9a9SClaudio Takahasi 
42283300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
42293300d9a9SClaudio Takahasi 		err = l2cap_config_rsp(conn, cmd, data);
42303300d9a9SClaudio Takahasi 		break;
42313300d9a9SClaudio Takahasi 
42323300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
42333300d9a9SClaudio Takahasi 		err = l2cap_disconnect_req(conn, cmd, data);
42343300d9a9SClaudio Takahasi 		break;
42353300d9a9SClaudio Takahasi 
42363300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
42373300d9a9SClaudio Takahasi 		err = l2cap_disconnect_rsp(conn, cmd, data);
42383300d9a9SClaudio Takahasi 		break;
42393300d9a9SClaudio Takahasi 
42403300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
42413300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
42423300d9a9SClaudio Takahasi 		break;
42433300d9a9SClaudio Takahasi 
42443300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
42453300d9a9SClaudio Takahasi 		break;
42463300d9a9SClaudio Takahasi 
42473300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
42483300d9a9SClaudio Takahasi 		err = l2cap_information_req(conn, cmd, data);
42493300d9a9SClaudio Takahasi 		break;
42503300d9a9SClaudio Takahasi 
42513300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
42523300d9a9SClaudio Takahasi 		err = l2cap_information_rsp(conn, cmd, data);
42533300d9a9SClaudio Takahasi 		break;
42543300d9a9SClaudio Takahasi 
4255f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
4256f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
4257f94ff6ffSMat Martineau 		break;
4258f94ff6ffSMat Martineau 
4259f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
4260f94ff6ffSMat Martineau 		err = l2cap_create_channel_rsp(conn, cmd, data);
4261f94ff6ffSMat Martineau 		break;
4262f94ff6ffSMat Martineau 
42638d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
42648d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
42658d5a04a1SMat Martineau 		break;
42668d5a04a1SMat Martineau 
42678d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
42688d5a04a1SMat Martineau 		err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
42698d5a04a1SMat Martineau 		break;
42708d5a04a1SMat Martineau 
42718d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
42728d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
42738d5a04a1SMat Martineau 		break;
42748d5a04a1SMat Martineau 
42758d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
42768d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
42778d5a04a1SMat Martineau 		break;
42788d5a04a1SMat Martineau 
42793300d9a9SClaudio Takahasi 	default:
42803300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
42813300d9a9SClaudio Takahasi 		err = -EINVAL;
42823300d9a9SClaudio Takahasi 		break;
42833300d9a9SClaudio Takahasi 	}
42843300d9a9SClaudio Takahasi 
42853300d9a9SClaudio Takahasi 	return err;
42863300d9a9SClaudio Takahasi }
42873300d9a9SClaudio Takahasi 
42883300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
42893300d9a9SClaudio Takahasi 					struct l2cap_cmd_hdr *cmd, u8 *data)
42903300d9a9SClaudio Takahasi {
42913300d9a9SClaudio Takahasi 	switch (cmd->code) {
42923300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
42933300d9a9SClaudio Takahasi 		return 0;
42943300d9a9SClaudio Takahasi 
42953300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
4296de73115aSClaudio Takahasi 		return l2cap_conn_param_update_req(conn, cmd, data);
42973300d9a9SClaudio Takahasi 
42983300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
42993300d9a9SClaudio Takahasi 		return 0;
43003300d9a9SClaudio Takahasi 
43013300d9a9SClaudio Takahasi 	default:
43023300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
43033300d9a9SClaudio Takahasi 		return -EINVAL;
43043300d9a9SClaudio Takahasi 	}
43053300d9a9SClaudio Takahasi }
43063300d9a9SClaudio Takahasi 
43073300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
43083300d9a9SClaudio Takahasi 							struct sk_buff *skb)
43090a708f8fSGustavo F. Padovan {
43100a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
43110a708f8fSGustavo F. Padovan 	int len = skb->len;
43120a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
43133300d9a9SClaudio Takahasi 	int err;
43140a708f8fSGustavo F. Padovan 
43150a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
43160a708f8fSGustavo F. Padovan 
43170a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
43180a708f8fSGustavo F. Padovan 		u16 cmd_len;
43190a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
43200a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
43210a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
43220a708f8fSGustavo F. Padovan 
43230a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
43240a708f8fSGustavo F. Padovan 
43250a708f8fSGustavo F. Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
43260a708f8fSGustavo F. Padovan 
43270a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
43280a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
43290a708f8fSGustavo F. Padovan 			break;
43300a708f8fSGustavo F. Padovan 		}
43310a708f8fSGustavo F. Padovan 
43323300d9a9SClaudio Takahasi 		if (conn->hcon->type == LE_LINK)
43333300d9a9SClaudio Takahasi 			err = l2cap_le_sig_cmd(conn, &cmd, data);
43343300d9a9SClaudio Takahasi 		else
43353300d9a9SClaudio Takahasi 			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
43360a708f8fSGustavo F. Padovan 
43370a708f8fSGustavo F. Padovan 		if (err) {
4338e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
43392c6d1a2eSGustavo F. Padovan 
43402c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
43410a708f8fSGustavo F. Padovan 
43420a708f8fSGustavo F. Padovan 			/* FIXME: Map err to a valid reason */
4343e2fd318eSIlia Kolomisnky 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
43440a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
43450a708f8fSGustavo F. Padovan 		}
43460a708f8fSGustavo F. Padovan 
43470a708f8fSGustavo F. Padovan 		data += cmd_len;
43480a708f8fSGustavo F. Padovan 		len  -= cmd_len;
43490a708f8fSGustavo F. Padovan 	}
43500a708f8fSGustavo F. Padovan 
43510a708f8fSGustavo F. Padovan 	kfree_skb(skb);
43520a708f8fSGustavo F. Padovan }
43530a708f8fSGustavo F. Padovan 
435447d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
43550a708f8fSGustavo F. Padovan {
43560a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
4357e4ca6d98SAndrei Emeltchenko 	int hdr_size;
4358e4ca6d98SAndrei Emeltchenko 
4359e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4360e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
4361e4ca6d98SAndrei Emeltchenko 	else
4362e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
43630a708f8fSGustavo F. Padovan 
436447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
436503a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
43660a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
43670a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
43680a708f8fSGustavo F. Padovan 
43690a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
43700a708f8fSGustavo F. Padovan 			return -EBADMSG;
43710a708f8fSGustavo F. Padovan 	}
43720a708f8fSGustavo F. Padovan 	return 0;
43730a708f8fSGustavo F. Padovan }
43740a708f8fSGustavo F. Padovan 
43756ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
43760a708f8fSGustavo F. Padovan {
4377e31f7633SMat Martineau 	struct l2cap_ctrl control;
43780a708f8fSGustavo F. Padovan 
4379e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
43800a708f8fSGustavo F. Padovan 
4381e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
4382e31f7633SMat Martineau 	control.sframe = 1;
4383e31f7633SMat Martineau 	control.final = 1;
4384e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
4385e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
43860a708f8fSGustavo F. Padovan 
4387e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4388e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
4389e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
43900a708f8fSGustavo F. Padovan 	}
43910a708f8fSGustavo F. Padovan 
4392e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4393e31f7633SMat Martineau 	    chan->unacked_frames > 0)
4394e31f7633SMat Martineau 		__set_retrans_timer(chan);
43950a708f8fSGustavo F. Padovan 
4396e31f7633SMat Martineau 	/* Send pending iframes */
4397525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
43980a708f8fSGustavo F. Padovan 
4399e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4400e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4401e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
4402e31f7633SMat Martineau 		 * send it now.
4403e31f7633SMat Martineau 		 */
4404e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
4405e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
44060a708f8fSGustavo F. Padovan 	}
44070a708f8fSGustavo F. Padovan }
44080a708f8fSGustavo F. Padovan 
440984084a31SMat Martineau static void append_skb_frag(struct sk_buff *skb,
441084084a31SMat Martineau 			struct sk_buff *new_frag, struct sk_buff **last_frag)
44110a708f8fSGustavo F. Padovan {
441284084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
441384084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
441484084a31SMat Martineau 	 */
441584084a31SMat Martineau 	if (!skb_has_frag_list(skb))
441684084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
441784084a31SMat Martineau 
441884084a31SMat Martineau 	new_frag->next = NULL;
441984084a31SMat Martineau 
442084084a31SMat Martineau 	(*last_frag)->next = new_frag;
442184084a31SMat Martineau 	*last_frag = new_frag;
442284084a31SMat Martineau 
442384084a31SMat Martineau 	skb->len += new_frag->len;
442484084a31SMat Martineau 	skb->data_len += new_frag->len;
442584084a31SMat Martineau 	skb->truesize += new_frag->truesize;
442684084a31SMat Martineau }
442784084a31SMat Martineau 
44284b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
44294b51dae9SMat Martineau 				struct l2cap_ctrl *control)
443084084a31SMat Martineau {
443184084a31SMat Martineau 	int err = -EINVAL;
44320a708f8fSGustavo F. Padovan 
44334b51dae9SMat Martineau 	switch (control->sar) {
44347e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
443584084a31SMat Martineau 		if (chan->sdu)
443684084a31SMat Martineau 			break;
44370a708f8fSGustavo F. Padovan 
443884084a31SMat Martineau 		err = chan->ops->recv(chan->data, skb);
443984084a31SMat Martineau 		break;
44400a708f8fSGustavo F. Padovan 
44417e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
444284084a31SMat Martineau 		if (chan->sdu)
444384084a31SMat Martineau 			break;
44440a708f8fSGustavo F. Padovan 
44456f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
444603a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
44470a708f8fSGustavo F. Padovan 
444884084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
444984084a31SMat Martineau 			err = -EMSGSIZE;
445084084a31SMat Martineau 			break;
445184084a31SMat Martineau 		}
44520a708f8fSGustavo F. Padovan 
445384084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
445484084a31SMat Martineau 			break;
445584084a31SMat Martineau 
445684084a31SMat Martineau 		chan->sdu = skb;
445784084a31SMat Martineau 		chan->sdu_last_frag = skb;
445884084a31SMat Martineau 
445984084a31SMat Martineau 		skb = NULL;
446084084a31SMat Martineau 		err = 0;
44610a708f8fSGustavo F. Padovan 		break;
44620a708f8fSGustavo F. Padovan 
44637e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
44646f61fd47SGustavo F. Padovan 		if (!chan->sdu)
446584084a31SMat Martineau 			break;
44660a708f8fSGustavo F. Padovan 
446784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
446884084a31SMat Martineau 				&chan->sdu_last_frag);
446984084a31SMat Martineau 		skb = NULL;
44700a708f8fSGustavo F. Padovan 
447184084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
447284084a31SMat Martineau 			break;
44730a708f8fSGustavo F. Padovan 
447484084a31SMat Martineau 		err = 0;
44750a708f8fSGustavo F. Padovan 		break;
44760a708f8fSGustavo F. Padovan 
44777e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
44786f61fd47SGustavo F. Padovan 		if (!chan->sdu)
447984084a31SMat Martineau 			break;
44800a708f8fSGustavo F. Padovan 
448184084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
448284084a31SMat Martineau 				&chan->sdu_last_frag);
448384084a31SMat Martineau 		skb = NULL;
44840a708f8fSGustavo F. Padovan 
448584084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
448684084a31SMat Martineau 			break;
44870a708f8fSGustavo F. Padovan 
448884084a31SMat Martineau 		err = chan->ops->recv(chan->data, chan->sdu);
44890a708f8fSGustavo F. Padovan 
449084084a31SMat Martineau 		if (!err) {
449184084a31SMat Martineau 			/* Reassembly complete */
449284084a31SMat Martineau 			chan->sdu = NULL;
449384084a31SMat Martineau 			chan->sdu_last_frag = NULL;
449484084a31SMat Martineau 			chan->sdu_len = 0;
44950a708f8fSGustavo F. Padovan 		}
44960a708f8fSGustavo F. Padovan 		break;
44970a708f8fSGustavo F. Padovan 	}
44980a708f8fSGustavo F. Padovan 
449984084a31SMat Martineau 	if (err) {
45000a708f8fSGustavo F. Padovan 		kfree_skb(skb);
45016f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
45026f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
450384084a31SMat Martineau 		chan->sdu_last_frag = NULL;
450484084a31SMat Martineau 		chan->sdu_len = 0;
450584084a31SMat Martineau 	}
45060a708f8fSGustavo F. Padovan 
450784084a31SMat Martineau 	return err;
45080a708f8fSGustavo F. Padovan }
45090a708f8fSGustavo F. Padovan 
4510e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
45110a708f8fSGustavo F. Padovan {
451261aa4f5bSMat Martineau 	u8 event;
451361aa4f5bSMat Martineau 
451461aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
451561aa4f5bSMat Martineau 		return;
451661aa4f5bSMat Martineau 
451761aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
4518401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
45190a708f8fSGustavo F. Padovan }
45200a708f8fSGustavo F. Padovan 
4521d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
4522d2a7ac5dSMat Martineau {
452363838725SMat Martineau 	int err = 0;
452463838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
452563838725SMat Martineau 	 * until a gap is encountered.
452663838725SMat Martineau 	 */
452763838725SMat Martineau 
452863838725SMat Martineau 	BT_DBG("chan %p", chan);
452963838725SMat Martineau 
453063838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
453163838725SMat Martineau 		struct sk_buff *skb;
453263838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
453363838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
453463838725SMat Martineau 
453563838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
453663838725SMat Martineau 
453763838725SMat Martineau 		if (!skb)
453863838725SMat Martineau 			break;
453963838725SMat Martineau 
454063838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
454163838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
454263838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
454363838725SMat Martineau 		if (err)
454463838725SMat Martineau 			break;
454563838725SMat Martineau 	}
454663838725SMat Martineau 
454763838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
454863838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
454963838725SMat Martineau 		l2cap_send_ack(chan);
455063838725SMat Martineau 	}
455163838725SMat Martineau 
455263838725SMat Martineau 	return err;
4553d2a7ac5dSMat Martineau }
4554d2a7ac5dSMat Martineau 
4555d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
4556d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
4557d2a7ac5dSMat Martineau {
4558f80842a8SMat Martineau 	struct sk_buff *skb;
4559f80842a8SMat Martineau 
4560f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4561f80842a8SMat Martineau 
4562f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4563f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4564f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4565f80842a8SMat Martineau 		return;
4566f80842a8SMat Martineau 	}
4567f80842a8SMat Martineau 
4568f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4569f80842a8SMat Martineau 
4570f80842a8SMat Martineau 	if (skb == NULL) {
4571f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
4572f80842a8SMat Martineau 		       control->reqseq);
4573f80842a8SMat Martineau 		return;
4574f80842a8SMat Martineau 	}
4575f80842a8SMat Martineau 
4576f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
4577f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4578f80842a8SMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4579f80842a8SMat Martineau 		return;
4580f80842a8SMat Martineau 	}
4581f80842a8SMat Martineau 
4582f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4583f80842a8SMat Martineau 
4584f80842a8SMat Martineau 	if (control->poll) {
4585f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
4586f80842a8SMat Martineau 
4587f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
4588f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
4589f80842a8SMat Martineau 		l2cap_ertm_send(chan);
4590f80842a8SMat Martineau 
4591f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4592f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
4593f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
4594f80842a8SMat Martineau 		}
4595f80842a8SMat Martineau 	} else {
4596f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
4597f80842a8SMat Martineau 
4598f80842a8SMat Martineau 		if (control->final) {
4599f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
4600f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
4601f80842a8SMat Martineau 						&chan->conn_state))
4602f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
4603f80842a8SMat Martineau 		} else {
4604f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
4605f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
4606f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
4607f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
4608f80842a8SMat Martineau 			}
4609f80842a8SMat Martineau 		}
4610f80842a8SMat Martineau 	}
4611d2a7ac5dSMat Martineau }
4612d2a7ac5dSMat Martineau 
4613d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
4614d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
4615d2a7ac5dSMat Martineau {
4616fcd289dfSMat Martineau 	struct sk_buff *skb;
4617fcd289dfSMat Martineau 
4618fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
4619fcd289dfSMat Martineau 
4620fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
4621fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
4622fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4623fcd289dfSMat Martineau 		return;
4624fcd289dfSMat Martineau 	}
4625fcd289dfSMat Martineau 
4626fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
4627fcd289dfSMat Martineau 
4628fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
4629fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
4630fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
4631fcd289dfSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
4632fcd289dfSMat Martineau 		return;
4633fcd289dfSMat Martineau 	}
4634fcd289dfSMat Martineau 
4635fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4636fcd289dfSMat Martineau 
4637fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
4638fcd289dfSMat Martineau 
4639fcd289dfSMat Martineau 	if (control->final) {
4640fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
4641fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
4642fcd289dfSMat Martineau 	} else {
4643fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
4644fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
4645fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
4646fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
4647fcd289dfSMat Martineau 	}
4648d2a7ac5dSMat Martineau }
4649d2a7ac5dSMat Martineau 
46504b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
46514b51dae9SMat Martineau {
46524b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
46534b51dae9SMat Martineau 
46544b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
46554b51dae9SMat Martineau 	       chan->expected_tx_seq);
46564b51dae9SMat Martineau 
46574b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
46584b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46594b51dae9SMat Martineau 								chan->tx_win) {
46604b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
46614b51dae9SMat Martineau 			 * invalid packets.
46624b51dae9SMat Martineau 			 */
46634b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
46644b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
46654b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
46664b51dae9SMat Martineau 			} else {
46674b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
46684b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
46694b51dae9SMat Martineau 			}
46704b51dae9SMat Martineau 		}
46714b51dae9SMat Martineau 
46724b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
46734b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
46744b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
46754b51dae9SMat Martineau 		}
46764b51dae9SMat Martineau 
46774b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
46784b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
46794b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
46804b51dae9SMat Martineau 		}
46814b51dae9SMat Martineau 
46824b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
46834b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
46844b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
46854b51dae9SMat Martineau 		}
46864b51dae9SMat Martineau 	}
46874b51dae9SMat Martineau 
46884b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
46894b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
46904b51dae9SMat Martineau 		    chan->tx_win) {
46914b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
46924b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
46934b51dae9SMat Martineau 		} else {
46944b51dae9SMat Martineau 			BT_DBG("Expected");
46954b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
46964b51dae9SMat Martineau 		}
46974b51dae9SMat Martineau 	}
46984b51dae9SMat Martineau 
46994b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
47004b51dae9SMat Martineau 		__seq_offset(chan, chan->expected_tx_seq,
47014b51dae9SMat Martineau 			     chan->last_acked_seq)){
47024b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
47034b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
47044b51dae9SMat Martineau 	}
47054b51dae9SMat Martineau 
47064b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
47074b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
47084b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
47094b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
47104b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
47114b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
47124b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
47134b51dae9SMat Martineau 		 * request.
47144b51dae9SMat Martineau 		 *
47154b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
47164b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
47174b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
47184b51dae9SMat Martineau 		 *
47194b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
47204b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
47214b51dae9SMat Martineau 		 * causes a disconnect.
47224b51dae9SMat Martineau 		 */
47234b51dae9SMat Martineau 
47244b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
47254b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
47264b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
47274b51dae9SMat Martineau 		} else {
47284b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
47294b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
47304b51dae9SMat Martineau 		}
47314b51dae9SMat Martineau 	} else {
47324b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
47334b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
47344b51dae9SMat Martineau 	}
47354b51dae9SMat Martineau }
47364b51dae9SMat Martineau 
4737d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
4738d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
4739d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
4740d2a7ac5dSMat Martineau {
4741d2a7ac5dSMat Martineau 	int err = 0;
4742d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4743d2a7ac5dSMat Martineau 
4744d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4745d2a7ac5dSMat Martineau 	       event);
4746d2a7ac5dSMat Martineau 
4747d2a7ac5dSMat Martineau 	switch (event) {
4748d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4749d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
4750d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4751d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4752d2a7ac5dSMat Martineau 
4753d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4754d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
4755d2a7ac5dSMat Martineau 				       control->txseq);
4756d2a7ac5dSMat Martineau 				break;
4757d2a7ac5dSMat Martineau 			}
4758d2a7ac5dSMat Martineau 
4759d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
4760d2a7ac5dSMat Martineau 							   control->txseq);
4761d2a7ac5dSMat Martineau 
4762d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
4763d2a7ac5dSMat Martineau 			skb_in_use = 1;
4764d2a7ac5dSMat Martineau 
4765d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
4766d2a7ac5dSMat Martineau 			if (err)
4767d2a7ac5dSMat Martineau 				break;
4768d2a7ac5dSMat Martineau 
4769d2a7ac5dSMat Martineau 			if (control->final) {
4770d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
4771d2a7ac5dSMat Martineau 							&chan->conn_state)) {
4772d2a7ac5dSMat Martineau 					control->final = 0;
4773d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
4774d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
4775d2a7ac5dSMat Martineau 				}
4776d2a7ac5dSMat Martineau 			}
4777d2a7ac5dSMat Martineau 
4778d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
4779d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
4780d2a7ac5dSMat Martineau 			break;
4781d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4782d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4783d2a7ac5dSMat Martineau 
4784d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
4785d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
4786d2a7ac5dSMat Martineau 			 * when local busy is exited.
4787d2a7ac5dSMat Martineau 			 */
4788d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4789d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
4790d2a7ac5dSMat Martineau 				       control->txseq);
4791d2a7ac5dSMat Martineau 				break;
4792d2a7ac5dSMat Martineau 			}
4793d2a7ac5dSMat Martineau 
4794d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
4795d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
4796d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
4797d2a7ac5dSMat Martineau 			 */
4798d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4799d2a7ac5dSMat Martineau 			skb_in_use = 1;
4800d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4801d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4802d2a7ac5dSMat Martineau 
4803d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
4804d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
4805d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4806d2a7ac5dSMat Martineau 
4807d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
4808d2a7ac5dSMat Martineau 			break;
4809d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4810d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4811d2a7ac5dSMat Martineau 			break;
4812d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4813d2a7ac5dSMat Martineau 			break;
4814d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4815d2a7ac5dSMat Martineau 		default:
4816d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4817d2a7ac5dSMat Martineau 					       ECONNRESET);
4818d2a7ac5dSMat Martineau 			break;
4819d2a7ac5dSMat Martineau 		}
4820d2a7ac5dSMat Martineau 		break;
4821d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4822d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4823d2a7ac5dSMat Martineau 		if (control->final) {
4824d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4825d2a7ac5dSMat Martineau 
4826d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4827d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4828d2a7ac5dSMat Martineau 				control->final = 0;
4829d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4830d2a7ac5dSMat Martineau 			}
4831d2a7ac5dSMat Martineau 
4832d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4833d2a7ac5dSMat Martineau 		} else if (control->poll) {
4834d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
4835d2a7ac5dSMat Martineau 		} else {
4836d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4837d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4838d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4839d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4840d2a7ac5dSMat Martineau 
4841d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4842d2a7ac5dSMat Martineau 		}
4843d2a7ac5dSMat Martineau 		break;
4844d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4845d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4846d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4847d2a7ac5dSMat Martineau 		if (control && control->poll) {
4848d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4849d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
4850d2a7ac5dSMat Martineau 		}
4851d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
4852d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
4853d2a7ac5dSMat Martineau 		break;
4854d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
4855d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
4856d2a7ac5dSMat Martineau 		break;
4857d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
4858d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
4859d2a7ac5dSMat Martineau 		break;
4860d2a7ac5dSMat Martineau 	default:
4861d2a7ac5dSMat Martineau 		break;
4862d2a7ac5dSMat Martineau 	}
4863d2a7ac5dSMat Martineau 
4864d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
4865d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
4866d2a7ac5dSMat Martineau 		kfree_skb(skb);
4867d2a7ac5dSMat Martineau 	}
4868d2a7ac5dSMat Martineau 
4869d2a7ac5dSMat Martineau 	return err;
4870d2a7ac5dSMat Martineau }
4871d2a7ac5dSMat Martineau 
4872d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
4873d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
4874d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
4875d2a7ac5dSMat Martineau {
4876d2a7ac5dSMat Martineau 	int err = 0;
4877d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
4878d2a7ac5dSMat Martineau 	bool skb_in_use = 0;
4879d2a7ac5dSMat Martineau 
4880d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
4881d2a7ac5dSMat Martineau 	       event);
4882d2a7ac5dSMat Martineau 
4883d2a7ac5dSMat Martineau 	switch (event) {
4884d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
4885d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
4886d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
4887d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
4888d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4889d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4890d2a7ac5dSMat Martineau 			skb_in_use = 1;
4891d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4892d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4893d2a7ac5dSMat Martineau 
4894d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
4895d2a7ac5dSMat Martineau 			break;
4896d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
4897d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
4898d2a7ac5dSMat Martineau 
4899d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4900d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4901d2a7ac5dSMat Martineau 			skb_in_use = 1;
4902d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4903d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4904d2a7ac5dSMat Martineau 
4905d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
4906d2a7ac5dSMat Martineau 			if (err)
4907d2a7ac5dSMat Martineau 				break;
4908d2a7ac5dSMat Martineau 
4909d2a7ac5dSMat Martineau 			break;
4910d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
4911d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
4912d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
4913d2a7ac5dSMat Martineau 			 * the missing frames.
4914d2a7ac5dSMat Martineau 			 */
4915d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4916d2a7ac5dSMat Martineau 			skb_in_use = 1;
4917d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4918d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4919d2a7ac5dSMat Martineau 
4920d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4921d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
4922d2a7ac5dSMat Martineau 			break;
4923d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
4924d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
4925d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
4926d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
4927d2a7ac5dSMat Martineau 			 * SREJ'd frames.
4928d2a7ac5dSMat Martineau 			 */
4929d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
4930d2a7ac5dSMat Martineau 			skb_in_use = 1;
4931d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
4932d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
4933d2a7ac5dSMat Martineau 
4934d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4935d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
4936d2a7ac5dSMat Martineau 			break;
4937d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
4938d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
4939d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
4940d2a7ac5dSMat Martineau 			break;
4941d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
4942d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
4943d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
4944d2a7ac5dSMat Martineau 			 */
4945d2a7ac5dSMat Martineau 			break;
4946d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
4947d2a7ac5dSMat Martineau 			break;
4948d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
4949d2a7ac5dSMat Martineau 		default:
4950d2a7ac5dSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
4951d2a7ac5dSMat Martineau 					       ECONNRESET);
4952d2a7ac5dSMat Martineau 			break;
4953d2a7ac5dSMat Martineau 		}
4954d2a7ac5dSMat Martineau 		break;
4955d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
4956d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4957d2a7ac5dSMat Martineau 		if (control->final) {
4958d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4959d2a7ac5dSMat Martineau 
4960d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
4961d2a7ac5dSMat Martineau 						&chan->conn_state)) {
4962d2a7ac5dSMat Martineau 				control->final = 0;
4963d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
4964d2a7ac5dSMat Martineau 			}
4965d2a7ac5dSMat Martineau 
4966d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
4967d2a7ac5dSMat Martineau 		} else if (control->poll) {
4968d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4969d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4970d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
4971d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4972d2a7ac5dSMat Martineau 			}
4973d2a7ac5dSMat Martineau 
4974d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
4975d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4976d2a7ac5dSMat Martineau 		} else {
4977d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
4978d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
4979d2a7ac5dSMat Martineau 			    chan->unacked_frames)
4980d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
4981d2a7ac5dSMat Martineau 
4982d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
4983d2a7ac5dSMat Martineau 		}
4984d2a7ac5dSMat Martineau 		break;
4985d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
4986d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
4987d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
4988d2a7ac5dSMat Martineau 		if (control->poll) {
4989d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
4990d2a7ac5dSMat Martineau 		} else {
4991d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
4992d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
4993d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
4994d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
4995d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
4996d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
4997d2a7ac5dSMat Martineau 		}
4998d2a7ac5dSMat Martineau 
4999d2a7ac5dSMat Martineau 		break;
5000d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
5001d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
5002d2a7ac5dSMat Martineau 		break;
5003d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
5004d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
5005d2a7ac5dSMat Martineau 		break;
5006d2a7ac5dSMat Martineau 	}
5007d2a7ac5dSMat Martineau 
5008d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
5009d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
5010d2a7ac5dSMat Martineau 		kfree_skb(skb);
5011d2a7ac5dSMat Martineau 	}
5012d2a7ac5dSMat Martineau 
5013d2a7ac5dSMat Martineau 	return err;
5014d2a7ac5dSMat Martineau }
5015d2a7ac5dSMat Martineau 
5016d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
5017d2a7ac5dSMat Martineau {
5018d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
5019d2a7ac5dSMat Martineau 	u16 unacked;
5020d2a7ac5dSMat Martineau 
5021d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
5022d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
5023d2a7ac5dSMat Martineau }
5024d2a7ac5dSMat Martineau 
5025cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5026cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
50270a708f8fSGustavo F. Padovan {
5028d2a7ac5dSMat Martineau 	int err = 0;
5029d2a7ac5dSMat Martineau 
5030d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
5031d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
5032d2a7ac5dSMat Martineau 
5033d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
5034d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
5035d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
5036d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
5037d2a7ac5dSMat Martineau 			break;
5038d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
5039d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
5040d2a7ac5dSMat Martineau 						       event);
5041d2a7ac5dSMat Martineau 			break;
5042d2a7ac5dSMat Martineau 		default:
5043d2a7ac5dSMat Martineau 			/* shut it down */
5044d2a7ac5dSMat Martineau 			break;
5045d2a7ac5dSMat Martineau 		}
5046d2a7ac5dSMat Martineau 	} else {
5047d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
5048d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
5049d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
5050d2a7ac5dSMat Martineau 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
5051d2a7ac5dSMat Martineau 	}
5052d2a7ac5dSMat Martineau 
5053d2a7ac5dSMat Martineau 	return err;
5054cec8ab6eSMat Martineau }
5055cec8ab6eSMat Martineau 
5056cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
5057cec8ab6eSMat Martineau 			   struct sk_buff *skb)
5058cec8ab6eSMat Martineau {
50594b51dae9SMat Martineau 	int err = 0;
50604b51dae9SMat Martineau 
50614b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
50624b51dae9SMat Martineau 	       chan->rx_state);
50634b51dae9SMat Martineau 
50644b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
50654b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
50664b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
50674b51dae9SMat Martineau 
50684b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
50694b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
50704b51dae9SMat Martineau 
50714b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
50724b51dae9SMat Martineau 
50734b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
50744b51dae9SMat Martineau 	} else {
50754b51dae9SMat Martineau 		if (chan->sdu) {
50764b51dae9SMat Martineau 			kfree_skb(chan->sdu);
50774b51dae9SMat Martineau 			chan->sdu = NULL;
50784b51dae9SMat Martineau 		}
50794b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
50804b51dae9SMat Martineau 		chan->sdu_len = 0;
50814b51dae9SMat Martineau 
50824b51dae9SMat Martineau 		if (skb) {
50834b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
50844b51dae9SMat Martineau 			kfree_skb(skb);
50854b51dae9SMat Martineau 		}
50864b51dae9SMat Martineau 	}
50874b51dae9SMat Martineau 
50884b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
50894b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
50904b51dae9SMat Martineau 
50914b51dae9SMat Martineau 	return err;
5092cec8ab6eSMat Martineau }
5093cec8ab6eSMat Martineau 
5094cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
5095cec8ab6eSMat Martineau {
5096cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
5097cec8ab6eSMat Martineau 	u16 len;
5098cec8ab6eSMat Martineau 	u8 event;
50990a708f8fSGustavo F. Padovan 
5100b76bbd66SMat Martineau 	__unpack_control(chan, skb);
5101b76bbd66SMat Martineau 
51020a708f8fSGustavo F. Padovan 	len = skb->len;
51030a708f8fSGustavo F. Padovan 
51040a708f8fSGustavo F. Padovan 	/*
51050a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
51060a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
5107cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
51080a708f8fSGustavo F. Padovan 	 */
510947d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
51100a708f8fSGustavo F. Padovan 		goto drop;
51110a708f8fSGustavo F. Padovan 
5112cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
511303a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
51140a708f8fSGustavo F. Padovan 
511547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
511603a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
51170a708f8fSGustavo F. Padovan 
511847d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
51198c1d787bSGustavo F. Padovan 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51200a708f8fSGustavo F. Padovan 		goto drop;
51210a708f8fSGustavo F. Padovan 	}
51220a708f8fSGustavo F. Padovan 
5123cec8ab6eSMat Martineau 	if (!control->sframe) {
5124cec8ab6eSMat Martineau 		int err;
51250a708f8fSGustavo F. Padovan 
5126cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
5127cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
5128cec8ab6eSMat Martineau 		       control->txseq);
5129836be934SAndrei Emeltchenko 
5130cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
5131cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
5132cec8ab6eSMat Martineau 		 */
5133cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
51340a708f8fSGustavo F. Padovan 			goto drop;
51350a708f8fSGustavo F. Padovan 
5136cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
5137cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
5138cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
51390a708f8fSGustavo F. Padovan 		} else {
5140cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
5141cec8ab6eSMat Martineau 		}
5142cec8ab6eSMat Martineau 
5143cec8ab6eSMat Martineau 		if (err)
5144cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan,
5145cec8ab6eSMat Martineau 					       ECONNRESET);
5146cec8ab6eSMat Martineau 	} else {
5147cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
5148cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
5149cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
5150cec8ab6eSMat Martineau 		};
5151cec8ab6eSMat Martineau 
5152cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
5153cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
5154cec8ab6eSMat Martineau 			goto drop;
5155cec8ab6eSMat Martineau 
5156cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
5157cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
5158cec8ab6eSMat Martineau 		       control->super);
5159cec8ab6eSMat Martineau 
51600a708f8fSGustavo F. Padovan 		if (len != 0) {
51610a708f8fSGustavo F. Padovan 			BT_ERR("%d", len);
51628c1d787bSGustavo F. Padovan 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51630a708f8fSGustavo F. Padovan 			goto drop;
51640a708f8fSGustavo F. Padovan 		}
51650a708f8fSGustavo F. Padovan 
5166cec8ab6eSMat Martineau 		/* Validate F and P bits */
5167cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
5168cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
5169cec8ab6eSMat Martineau 			goto drop;
5170cec8ab6eSMat Martineau 
5171cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
5172cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
5173cec8ab6eSMat Martineau 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
51740a708f8fSGustavo F. Padovan 	}
51750a708f8fSGustavo F. Padovan 
51760a708f8fSGustavo F. Padovan 	return 0;
51770a708f8fSGustavo F. Padovan 
51780a708f8fSGustavo F. Padovan drop:
51790a708f8fSGustavo F. Padovan 	kfree_skb(skb);
51800a708f8fSGustavo F. Padovan 	return 0;
51810a708f8fSGustavo F. Padovan }
51820a708f8fSGustavo F. Padovan 
51830a708f8fSGustavo F. Padovan static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
51840a708f8fSGustavo F. Padovan {
518548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
51860a708f8fSGustavo F. Padovan 
5187baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
518848454079SGustavo F. Padovan 	if (!chan) {
51890a708f8fSGustavo F. Padovan 		BT_DBG("unknown cid 0x%4.4x", cid);
51906be36555SAndrei Emeltchenko 		/* Drop packet and return */
51913379013bSDan Carpenter 		kfree_skb(skb);
51926be36555SAndrei Emeltchenko 		return 0;
51930a708f8fSGustavo F. Padovan 	}
51940a708f8fSGustavo F. Padovan 
519549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
51960a708f8fSGustavo F. Padovan 
519789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
51980a708f8fSGustavo F. Padovan 		goto drop;
51990a708f8fSGustavo F. Padovan 
52000c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
52010a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
52020a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
52030a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
52040a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
52050a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
52060a708f8fSGustavo F. Padovan 
52070c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
52080a708f8fSGustavo F. Padovan 			goto drop;
52090a708f8fSGustavo F. Padovan 
521023070494SGustavo F. Padovan 		if (!chan->ops->recv(chan->data, skb))
52110a708f8fSGustavo F. Padovan 			goto done;
52120a708f8fSGustavo F. Padovan 		break;
52130a708f8fSGustavo F. Padovan 
52140a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
52150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
5216cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
52170a708f8fSGustavo F. Padovan 		goto done;
52180a708f8fSGustavo F. Padovan 
52190a708f8fSGustavo F. Padovan 	default:
52200c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
52210a708f8fSGustavo F. Padovan 		break;
52220a708f8fSGustavo F. Padovan 	}
52230a708f8fSGustavo F. Padovan 
52240a708f8fSGustavo F. Padovan drop:
52250a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52260a708f8fSGustavo F. Padovan 
52270a708f8fSGustavo F. Padovan done:
52286be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
52290a708f8fSGustavo F. Padovan 
52300a708f8fSGustavo F. Padovan 	return 0;
52310a708f8fSGustavo F. Padovan }
52320a708f8fSGustavo F. Padovan 
52330a708f8fSGustavo F. Padovan static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
52340a708f8fSGustavo F. Padovan {
523523691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52360a708f8fSGustavo F. Padovan 
5237c2287681SIdo Yariv 	chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst);
523823691d75SGustavo F. Padovan 	if (!chan)
52390a708f8fSGustavo F. Padovan 		goto drop;
52400a708f8fSGustavo F. Padovan 
52415b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52420a708f8fSGustavo F. Padovan 
524389bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52440a708f8fSGustavo F. Padovan 		goto drop;
52450a708f8fSGustavo F. Padovan 
5246e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52470a708f8fSGustavo F. Padovan 		goto drop;
52480a708f8fSGustavo F. Padovan 
524923070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
52505b4cedaaSAndrei Emeltchenko 		return 0;
52510a708f8fSGustavo F. Padovan 
52520a708f8fSGustavo F. Padovan drop:
52530a708f8fSGustavo F. Padovan 	kfree_skb(skb);
52540a708f8fSGustavo F. Padovan 
52550a708f8fSGustavo F. Padovan 	return 0;
52560a708f8fSGustavo F. Padovan }
52570a708f8fSGustavo F. Padovan 
5258d9b88702SAndrei Emeltchenko static inline int l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
5259d9b88702SAndrei Emeltchenko 				    struct sk_buff *skb)
52609f69bda6SGustavo F. Padovan {
526123691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
52629f69bda6SGustavo F. Padovan 
5263c2287681SIdo Yariv 	chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
526423691d75SGustavo F. Padovan 	if (!chan)
52659f69bda6SGustavo F. Padovan 		goto drop;
52669f69bda6SGustavo F. Padovan 
52675b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
52689f69bda6SGustavo F. Padovan 
526989bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
52709f69bda6SGustavo F. Padovan 		goto drop;
52719f69bda6SGustavo F. Padovan 
5272e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
52739f69bda6SGustavo F. Padovan 		goto drop;
52749f69bda6SGustavo F. Padovan 
527523070494SGustavo F. Padovan 	if (!chan->ops->recv(chan->data, skb))
52765b4cedaaSAndrei Emeltchenko 		return 0;
52779f69bda6SGustavo F. Padovan 
52789f69bda6SGustavo F. Padovan drop:
52799f69bda6SGustavo F. Padovan 	kfree_skb(skb);
52809f69bda6SGustavo F. Padovan 
52819f69bda6SGustavo F. Padovan 	return 0;
52829f69bda6SGustavo F. Padovan }
52839f69bda6SGustavo F. Padovan 
52840a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
52850a708f8fSGustavo F. Padovan {
52860a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
52870a708f8fSGustavo F. Padovan 	u16 cid, len;
52880a708f8fSGustavo F. Padovan 	__le16 psm;
52890a708f8fSGustavo F. Padovan 
52900a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
52910a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
52920a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
52930a708f8fSGustavo F. Padovan 
52940a708f8fSGustavo F. Padovan 	if (len != skb->len) {
52950a708f8fSGustavo F. Padovan 		kfree_skb(skb);
52960a708f8fSGustavo F. Padovan 		return;
52970a708f8fSGustavo F. Padovan 	}
52980a708f8fSGustavo F. Padovan 
52990a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
53000a708f8fSGustavo F. Padovan 
53010a708f8fSGustavo F. Padovan 	switch (cid) {
53023300d9a9SClaudio Takahasi 	case L2CAP_CID_LE_SIGNALING:
53030a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
53040a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
53050a708f8fSGustavo F. Padovan 		break;
53060a708f8fSGustavo F. Padovan 
53070a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
5308097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
53090a708f8fSGustavo F. Padovan 		skb_pull(skb, 2);
53100a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
53110a708f8fSGustavo F. Padovan 		break;
53120a708f8fSGustavo F. Padovan 
53139f69bda6SGustavo F. Padovan 	case L2CAP_CID_LE_DATA:
53149f69bda6SGustavo F. Padovan 		l2cap_att_channel(conn, cid, skb);
53159f69bda6SGustavo F. Padovan 		break;
53169f69bda6SGustavo F. Padovan 
5317b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
5318b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
5319b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
5320b501d6a1SAnderson Briglia 		break;
5321b501d6a1SAnderson Briglia 
53220a708f8fSGustavo F. Padovan 	default:
53230a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
53240a708f8fSGustavo F. Padovan 		break;
53250a708f8fSGustavo F. Padovan 	}
53260a708f8fSGustavo F. Padovan }
53270a708f8fSGustavo F. Padovan 
53280a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
53290a708f8fSGustavo F. Padovan 
5330686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
53310a708f8fSGustavo F. Padovan {
53320a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
533323691d75SGustavo F. Padovan 	struct l2cap_chan *c;
53340a708f8fSGustavo F. Padovan 
53350a708f8fSGustavo F. Padovan 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
53360a708f8fSGustavo F. Padovan 
53370a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
533823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
533923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
534023691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
53414343478fSGustavo F. Padovan 
534289bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
53430a708f8fSGustavo F. Padovan 			continue;
53440a708f8fSGustavo F. Padovan 
53450a708f8fSGustavo F. Padovan 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
53460a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
534743bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53480a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
53490a708f8fSGustavo F. Padovan 			exact++;
53500a708f8fSGustavo F. Padovan 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
53510a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
535243bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
53530a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
53540a708f8fSGustavo F. Padovan 		}
53550a708f8fSGustavo F. Padovan 	}
535623691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
53570a708f8fSGustavo F. Padovan 
53580a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
53590a708f8fSGustavo F. Padovan }
53600a708f8fSGustavo F. Padovan 
5361686ebf28SUlisses Furquim int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
53620a708f8fSGustavo F. Padovan {
53630a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
53640a708f8fSGustavo F. Padovan 
53650a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
53660a708f8fSGustavo F. Padovan 
53670a708f8fSGustavo F. Padovan 	if (!status) {
53680a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, status);
53690a708f8fSGustavo F. Padovan 		if (conn)
53700a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
53710a708f8fSGustavo F. Padovan 	} else
5372e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
53730a708f8fSGustavo F. Padovan 
53740a708f8fSGustavo F. Padovan 	return 0;
53750a708f8fSGustavo F. Padovan }
53760a708f8fSGustavo F. Padovan 
5377686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
53780a708f8fSGustavo F. Padovan {
53790a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
53800a708f8fSGustavo F. Padovan 
53810a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
53820a708f8fSGustavo F. Padovan 
5383686ebf28SUlisses Furquim 	if (!conn)
53849f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
53850a708f8fSGustavo F. Padovan 	return conn->disc_reason;
53860a708f8fSGustavo F. Padovan }
53870a708f8fSGustavo F. Padovan 
5388686ebf28SUlisses Furquim int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
53890a708f8fSGustavo F. Padovan {
53900a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
53910a708f8fSGustavo F. Padovan 
5392e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
53930a708f8fSGustavo F. Padovan 	return 0;
53940a708f8fSGustavo F. Padovan }
53950a708f8fSGustavo F. Padovan 
53964343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
53970a708f8fSGustavo F. Padovan {
5398715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
53990a708f8fSGustavo F. Padovan 		return;
54000a708f8fSGustavo F. Padovan 
54010a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
54024343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
5403ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
54044343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
54050f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
54060a708f8fSGustavo F. Padovan 	} else {
54074343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
5408c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
54090a708f8fSGustavo F. Padovan 	}
54100a708f8fSGustavo F. Padovan }
54110a708f8fSGustavo F. Padovan 
5412686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
54130a708f8fSGustavo F. Padovan {
54140a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
541548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
54160a708f8fSGustavo F. Padovan 
54170a708f8fSGustavo F. Padovan 	if (!conn)
54180a708f8fSGustavo F. Padovan 		return 0;
54190a708f8fSGustavo F. Padovan 
54200a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
54210a708f8fSGustavo F. Padovan 
5422160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
542335d4adccSHemant Gupta 		if (!status && encrypt)
5424160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
542517cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
5426160dc6acSVinicius Costa Gomes 	}
5427160dc6acSVinicius Costa Gomes 
54283df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
54290a708f8fSGustavo F. Padovan 
54303df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
54316be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
54320a708f8fSGustavo F. Padovan 
5433f1cb9af5SVinicius Costa Gomes 		BT_DBG("chan->scid %d", chan->scid);
5434f1cb9af5SVinicius Costa Gomes 
5435f1cb9af5SVinicius Costa Gomes 		if (chan->scid == L2CAP_CID_LE_DATA) {
5436f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
5437f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
5438cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
5439f1cb9af5SVinicius Costa Gomes 			}
5440f1cb9af5SVinicius Costa Gomes 
54416be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
5442f1cb9af5SVinicius Costa Gomes 			continue;
5443f1cb9af5SVinicius Costa Gomes 		}
5444f1cb9af5SVinicius Costa Gomes 
5445c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
54466be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54470a708f8fSGustavo F. Padovan 			continue;
54480a708f8fSGustavo F. Padovan 		}
54490a708f8fSGustavo F. Padovan 
545089bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
545189bc500eSGustavo F. Padovan 						chan->state == BT_CONFIG)) {
5452a7d7723aSGustavo Padovan 			struct sock *sk = chan->sk;
5453a7d7723aSGustavo Padovan 
5454c5daa683SGustavo Padovan 			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
5455a7d7723aSGustavo Padovan 			sk->sk_state_change(sk);
5456a7d7723aSGustavo Padovan 
54574343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
54586be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
54590a708f8fSGustavo F. Padovan 			continue;
54600a708f8fSGustavo F. Padovan 		}
54610a708f8fSGustavo F. Padovan 
546289bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
54630a708f8fSGustavo F. Padovan 			if (!status) {
54649b27f350SAndrei Emeltchenko 				l2cap_send_conn_req(chan);
54650a708f8fSGustavo F. Padovan 			} else {
5466ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
54670a708f8fSGustavo F. Padovan 			}
546889bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
54696be36555SAndrei Emeltchenko 			struct sock *sk = chan->sk;
54700a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
5471df3c3931SJohan Hedberg 			__u16 res, stat;
54720a708f8fSGustavo F. Padovan 
54736be36555SAndrei Emeltchenko 			lock_sock(sk);
54746be36555SAndrei Emeltchenko 
54750a708f8fSGustavo F. Padovan 			if (!status) {
5476c5daa683SGustavo Padovan 				if (test_bit(BT_SK_DEFER_SETUP,
5477c5daa683SGustavo Padovan 					     &bt_sk(sk)->flags)) {
5478df3c3931SJohan Hedberg 					struct sock *parent = bt_sk(sk)->parent;
5479df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
5480df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
548105e9a2f6SIlia Kolomisnky 					if (parent)
5482df3c3931SJohan Hedberg 						parent->sk_data_ready(parent, 0);
5483df3c3931SJohan Hedberg 				} else {
54840e587be7SAndrei Emeltchenko 					__l2cap_state_change(chan, BT_CONFIG);
5485df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
5486df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
5487df3c3931SJohan Hedberg 				}
54880a708f8fSGustavo F. Padovan 			} else {
54890e587be7SAndrei Emeltchenko 				__l2cap_state_change(chan, BT_DISCONN);
5490ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
5491df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
5492df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
54930a708f8fSGustavo F. Padovan 			}
54940a708f8fSGustavo F. Padovan 
54956be36555SAndrei Emeltchenko 			release_sock(sk);
54966be36555SAndrei Emeltchenko 
5497fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
5498fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
5499df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
5500df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
5501fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
5502fc7f8a7eSGustavo F. Padovan 							sizeof(rsp), &rsp);
55030a708f8fSGustavo F. Padovan 		}
55040a708f8fSGustavo F. Padovan 
55056be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
55060a708f8fSGustavo F. Padovan 	}
55070a708f8fSGustavo F. Padovan 
55083df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
55090a708f8fSGustavo F. Padovan 
55100a708f8fSGustavo F. Padovan 	return 0;
55110a708f8fSGustavo F. Padovan }
55120a708f8fSGustavo F. Padovan 
5513686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
55140a708f8fSGustavo F. Padovan {
55150a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
55160a708f8fSGustavo F. Padovan 
55170a708f8fSGustavo F. Padovan 	if (!conn)
55180a708f8fSGustavo F. Padovan 		conn = l2cap_conn_add(hcon, 0);
55190a708f8fSGustavo F. Padovan 
55200a708f8fSGustavo F. Padovan 	if (!conn)
55210a708f8fSGustavo F. Padovan 		goto drop;
55220a708f8fSGustavo F. Padovan 
55230a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
55240a708f8fSGustavo F. Padovan 
55250a708f8fSGustavo F. Padovan 	if (!(flags & ACL_CONT)) {
55260a708f8fSGustavo F. Padovan 		struct l2cap_hdr *hdr;
55270a708f8fSGustavo F. Padovan 		int len;
55280a708f8fSGustavo F. Padovan 
55290a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
55300a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
55310a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55320a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55330a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55340a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55350a708f8fSGustavo F. Padovan 		}
55360a708f8fSGustavo F. Padovan 
55370a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
55380a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
55390a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
55400a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55410a708f8fSGustavo F. Padovan 			goto drop;
55420a708f8fSGustavo F. Padovan 		}
55430a708f8fSGustavo F. Padovan 
55440a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
55450a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
55460a708f8fSGustavo F. Padovan 
55470a708f8fSGustavo F. Padovan 		if (len == skb->len) {
55480a708f8fSGustavo F. Padovan 			/* Complete frame received */
55490a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
55500a708f8fSGustavo F. Padovan 			return 0;
55510a708f8fSGustavo F. Padovan 		}
55520a708f8fSGustavo F. Padovan 
55530a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
55540a708f8fSGustavo F. Padovan 
55550a708f8fSGustavo F. Padovan 		if (skb->len > len) {
55560a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
55570a708f8fSGustavo F. Padovan 				skb->len, len);
55580a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55590a708f8fSGustavo F. Padovan 			goto drop;
55600a708f8fSGustavo F. Padovan 		}
55610a708f8fSGustavo F. Padovan 
55620a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
55630a708f8fSGustavo F. Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
55640a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
55650a708f8fSGustavo F. Padovan 			goto drop;
55660a708f8fSGustavo F. Padovan 
55670a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55680a708f8fSGustavo F. Padovan 								skb->len);
55690a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
55700a708f8fSGustavo F. Padovan 	} else {
55710a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
55720a708f8fSGustavo F. Padovan 
55730a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
55740a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
55750a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55760a708f8fSGustavo F. Padovan 			goto drop;
55770a708f8fSGustavo F. Padovan 		}
55780a708f8fSGustavo F. Padovan 
55790a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
55800a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
55810a708f8fSGustavo F. Padovan 					skb->len, conn->rx_len);
55820a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
55830a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55840a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
55850a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
55860a708f8fSGustavo F. Padovan 			goto drop;
55870a708f8fSGustavo F. Padovan 		}
55880a708f8fSGustavo F. Padovan 
55890a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
55900a708f8fSGustavo F. Padovan 								skb->len);
55910a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
55920a708f8fSGustavo F. Padovan 
55930a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
55940a708f8fSGustavo F. Padovan 			/* Complete frame received */
55950a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, conn->rx_skb);
55960a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
55970a708f8fSGustavo F. Padovan 		}
55980a708f8fSGustavo F. Padovan 	}
55990a708f8fSGustavo F. Padovan 
56000a708f8fSGustavo F. Padovan drop:
56010a708f8fSGustavo F. Padovan 	kfree_skb(skb);
56020a708f8fSGustavo F. Padovan 	return 0;
56030a708f8fSGustavo F. Padovan }
56040a708f8fSGustavo F. Padovan 
56050a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
56060a708f8fSGustavo F. Padovan {
560723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
56080a708f8fSGustavo F. Padovan 
5609333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
56100a708f8fSGustavo F. Padovan 
561123691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
561223691d75SGustavo F. Padovan 		struct sock *sk = c->sk;
56130a708f8fSGustavo F. Padovan 
5614903d343eSGustavo F. Padovan 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
56150a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->src),
56160a708f8fSGustavo F. Padovan 					batostr(&bt_sk(sk)->dst),
561789bc500eSGustavo F. Padovan 					c->state, __le16_to_cpu(c->psm),
561823691d75SGustavo F. Padovan 					c->scid, c->dcid, c->imtu, c->omtu,
561923691d75SGustavo F. Padovan 					c->sec_level, c->mode);
56200a708f8fSGustavo F. Padovan 	}
56210a708f8fSGustavo F. Padovan 
5622333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
56230a708f8fSGustavo F. Padovan 
56240a708f8fSGustavo F. Padovan 	return 0;
56250a708f8fSGustavo F. Padovan }
56260a708f8fSGustavo F. Padovan 
56270a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
56280a708f8fSGustavo F. Padovan {
56290a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
56300a708f8fSGustavo F. Padovan }
56310a708f8fSGustavo F. Padovan 
56320a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
56330a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
56340a708f8fSGustavo F. Padovan 	.read		= seq_read,
56350a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
56360a708f8fSGustavo F. Padovan 	.release	= single_release,
56370a708f8fSGustavo F. Padovan };
56380a708f8fSGustavo F. Padovan 
56390a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
56400a708f8fSGustavo F. Padovan 
564164274518SGustavo F. Padovan int __init l2cap_init(void)
56420a708f8fSGustavo F. Padovan {
56430a708f8fSGustavo F. Padovan 	int err;
56440a708f8fSGustavo F. Padovan 
5645bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
56460a708f8fSGustavo F. Padovan 	if (err < 0)
56470a708f8fSGustavo F. Padovan 		return err;
56480a708f8fSGustavo F. Padovan 
56490a708f8fSGustavo F. Padovan 	if (bt_debugfs) {
56500a708f8fSGustavo F. Padovan 		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
56510a708f8fSGustavo F. Padovan 					bt_debugfs, NULL, &l2cap_debugfs_fops);
56520a708f8fSGustavo F. Padovan 		if (!l2cap_debugfs)
56530a708f8fSGustavo F. Padovan 			BT_ERR("Failed to create L2CAP debug file");
56540a708f8fSGustavo F. Padovan 	}
56550a708f8fSGustavo F. Padovan 
56560a708f8fSGustavo F. Padovan 	return 0;
56570a708f8fSGustavo F. Padovan }
56580a708f8fSGustavo F. Padovan 
565964274518SGustavo F. Padovan void l2cap_exit(void)
56600a708f8fSGustavo F. Padovan {
56610a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
5662bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
56630a708f8fSGustavo F. Padovan }
56640a708f8fSGustavo F. Padovan 
56650a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
56660a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
5667