xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 0ce43ce6)
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>
397ef9fbf0SMarcel Holtmann 
40ac4b7236SMarcel Holtmann #include "smp.h"
417024728eSMarcel Holtmann #include "a2mp.h"
427ef9fbf0SMarcel Holtmann #include "amp.h"
430a708f8fSGustavo F. Padovan 
44d1de6d46SMat Martineau bool disable_ertm;
450a708f8fSGustavo F. Padovan 
46547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
47d40bffbcSMarcel Holtmann static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
480a708f8fSGustavo F. Padovan 
49b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
50b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
510a708f8fSGustavo F. Padovan 
52f15b8ecfSJohan Hedberg static u16 le_max_credits = L2CAP_LE_MAX_CREDITS;
53f15b8ecfSJohan Hedberg static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS;
54f15b8ecfSJohan Hedberg 
550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
560a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
584519de9aSGustavo F. Padovan 			   void *data);
59710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
610a708f8fSGustavo F. Padovan 
62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
63608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
64608bcc6dSMat Martineau 
654f1654e0SMarcel Holtmann static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
664f1654e0SMarcel Holtmann {
674f1654e0SMarcel Holtmann 	if (hcon->type == LE_LINK) {
684f1654e0SMarcel Holtmann 		if (type == ADDR_LE_DEV_PUBLIC)
694f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
704f1654e0SMarcel Holtmann 		else
714f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
724f1654e0SMarcel Holtmann 	}
734f1654e0SMarcel Holtmann 
744f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
754f1654e0SMarcel Holtmann }
764f1654e0SMarcel Holtmann 
770a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7871ba0e56SGustavo F. Padovan 
792d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
802d792818SGustavo Padovan 						   u16 cid)
810a708f8fSGustavo F. Padovan {
823df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
83baa7e1faSGustavo F. Padovan 
843df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
853df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
863df91ea2SAndrei Emeltchenko 			return c;
870a708f8fSGustavo F. Padovan 	}
883df91ea2SAndrei Emeltchenko 	return NULL;
89baa7e1faSGustavo F. Padovan }
900a708f8fSGustavo F. Padovan 
912d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
922d792818SGustavo Padovan 						   u16 cid)
930a708f8fSGustavo F. Padovan {
943df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
95baa7e1faSGustavo F. Padovan 
963df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
973df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
983df91ea2SAndrei Emeltchenko 			return c;
990a708f8fSGustavo F. Padovan 	}
1003df91ea2SAndrei Emeltchenko 	return NULL;
101baa7e1faSGustavo F. Padovan }
1020a708f8fSGustavo F. Padovan 
1030a708f8fSGustavo F. Padovan /* Find channel with given SCID.
104ef191adeSMat Martineau  * Returns locked channel. */
1052d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1062d792818SGustavo Padovan 						 u16 cid)
1070a708f8fSGustavo F. Padovan {
10848454079SGustavo F. Padovan 	struct l2cap_chan *c;
109baa7e1faSGustavo F. Padovan 
1103df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
111baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
112ef191adeSMat Martineau 	if (c)
113ef191adeSMat Martineau 		l2cap_chan_lock(c);
1143df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1153df91ea2SAndrei Emeltchenko 
11648454079SGustavo F. Padovan 	return c;
1170a708f8fSGustavo F. Padovan }
1180a708f8fSGustavo F. Padovan 
119b1a130b7SMat Martineau /* Find channel with given DCID.
120b1a130b7SMat Martineau  * Returns locked channel.
121b1a130b7SMat Martineau  */
122b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
123b1a130b7SMat Martineau 						 u16 cid)
124b1a130b7SMat Martineau {
125b1a130b7SMat Martineau 	struct l2cap_chan *c;
126b1a130b7SMat Martineau 
127b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
128b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
129b1a130b7SMat Martineau 	if (c)
130b1a130b7SMat Martineau 		l2cap_chan_lock(c);
131b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
132b1a130b7SMat Martineau 
133b1a130b7SMat Martineau 	return c;
134b1a130b7SMat Martineau }
135b1a130b7SMat Martineau 
1362d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1372d792818SGustavo Padovan 						    u8 ident)
1380a708f8fSGustavo F. Padovan {
1393df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
140baa7e1faSGustavo F. Padovan 
1413df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1423df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1433df91ea2SAndrei Emeltchenko 			return c;
1440a708f8fSGustavo F. Padovan 	}
1453df91ea2SAndrei Emeltchenko 	return NULL;
146baa7e1faSGustavo F. Padovan }
1470a708f8fSGustavo F. Padovan 
1485b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1495b155ef9SMat Martineau 						  u8 ident)
1505b155ef9SMat Martineau {
1515b155ef9SMat Martineau 	struct l2cap_chan *c;
1525b155ef9SMat Martineau 
1535b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1545b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1555b155ef9SMat Martineau 	if (c)
1565b155ef9SMat Martineau 		l2cap_chan_lock(c);
1575b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1585b155ef9SMat Martineau 
1595b155ef9SMat Martineau 	return c;
1605b155ef9SMat Martineau }
1615b155ef9SMat Martineau 
16223691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1639e4425ffSGustavo F. Padovan {
16423691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1659e4425ffSGustavo F. Padovan 
16623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
1677eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
16823691d75SGustavo F. Padovan 			return c;
1699e4425ffSGustavo F. Padovan 	}
170250938cbSSzymon Janc 	return NULL;
171250938cbSSzymon Janc }
1729e4425ffSGustavo F. Padovan 
1739e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1749e4425ffSGustavo F. Padovan {
17573b2ec18SGustavo F. Padovan 	int err;
17673b2ec18SGustavo F. Padovan 
177333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1789e4425ffSGustavo F. Padovan 
17923691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
18073b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
18173b2ec18SGustavo F. Padovan 		goto done;
1829e4425ffSGustavo F. Padovan 	}
1839e4425ffSGustavo F. Padovan 
18473b2ec18SGustavo F. Padovan 	if (psm) {
1859e4425ffSGustavo F. Padovan 		chan->psm = psm;
1869e4425ffSGustavo F. Padovan 		chan->sport = psm;
18773b2ec18SGustavo F. Padovan 		err = 0;
18873b2ec18SGustavo F. Padovan 	} else {
18973b2ec18SGustavo F. Padovan 		u16 p;
1909e4425ffSGustavo F. Padovan 
19173b2ec18SGustavo F. Padovan 		err = -EINVAL;
19273b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
19323691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
19473b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
19573b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
19673b2ec18SGustavo F. Padovan 				err = 0;
19773b2ec18SGustavo F. Padovan 				break;
19873b2ec18SGustavo F. Padovan 			}
19973b2ec18SGustavo F. Padovan 	}
20073b2ec18SGustavo F. Padovan 
20173b2ec18SGustavo F. Padovan done:
202333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
20373b2ec18SGustavo F. Padovan 	return err;
2049e4425ffSGustavo F. Padovan }
2059e4425ffSGustavo F. Padovan 
2069e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2079e4425ffSGustavo F. Padovan {
208333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2099e4425ffSGustavo F. Padovan 
2109e4425ffSGustavo F. Padovan 	chan->scid = scid;
2119e4425ffSGustavo F. Padovan 
212333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2139e4425ffSGustavo F. Padovan 
2149e4425ffSGustavo F. Padovan 	return 0;
2159e4425ffSGustavo F. Padovan }
2169e4425ffSGustavo F. Padovan 
217baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2180a708f8fSGustavo F. Padovan {
219e77af755SJohan Hedberg 	u16 cid, dyn_end;
2200a708f8fSGustavo F. Padovan 
221e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
222e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
223e77af755SJohan Hedberg 	else
224e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
225e77af755SJohan Hedberg 
226e77af755SJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
227baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2280a708f8fSGustavo F. Padovan 			return cid;
2290a708f8fSGustavo F. Padovan 	}
2300a708f8fSGustavo F. Padovan 
2310a708f8fSGustavo F. Padovan 	return 0;
2320a708f8fSGustavo F. Padovan }
2330a708f8fSGustavo F. Padovan 
234f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
23589bc500eSGustavo F. Padovan {
23642d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
237badaaa00SGustavo F. Padovan 	       state_to_string(state));
238badaaa00SGustavo F. Padovan 
23989bc500eSGustavo F. Padovan 	chan->state = state;
24053f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
24189bc500eSGustavo F. Padovan }
24289bc500eSGustavo F. Padovan 
243f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
244f8e73017SGustavo Padovan 						int state, int err)
2452e0052e4SAndrei Emeltchenko {
246f8e73017SGustavo Padovan 	chan->state = state;
24753f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2482e0052e4SAndrei Emeltchenko }
2492e0052e4SAndrei Emeltchenko 
2502e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2512e0052e4SAndrei Emeltchenko {
252f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2532e0052e4SAndrei Emeltchenko }
2542e0052e4SAndrei Emeltchenko 
2554239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2564239d16fSMat Martineau {
2574239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2584239d16fSMat Martineau 	    chan->retrans_timeout) {
2594239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2604239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2614239d16fSMat Martineau 	}
2624239d16fSMat Martineau }
2634239d16fSMat Martineau 
2644239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2654239d16fSMat Martineau {
2664239d16fSMat Martineau 	__clear_retrans_timer(chan);
2674239d16fSMat Martineau 	if (chan->monitor_timeout) {
2684239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2694239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2704239d16fSMat Martineau 	}
2714239d16fSMat Martineau }
2724239d16fSMat Martineau 
273608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
274608bcc6dSMat Martineau 					       u16 seq)
275608bcc6dSMat Martineau {
276608bcc6dSMat Martineau 	struct sk_buff *skb;
277608bcc6dSMat Martineau 
278608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
279608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
280608bcc6dSMat Martineau 			return skb;
281608bcc6dSMat Martineau 	}
282608bcc6dSMat Martineau 
283608bcc6dSMat Martineau 	return NULL;
284608bcc6dSMat Martineau }
285608bcc6dSMat Martineau 
2863c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2873c588192SMat Martineau 
2883c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2893c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2903c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2913c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2923c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2933c588192SMat Martineau  * and removed from the head in constant time, without further memory
2943c588192SMat Martineau  * allocs or frees.
2953c588192SMat Martineau  */
2963c588192SMat Martineau 
2973c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2983c588192SMat Martineau {
2993c588192SMat Martineau 	size_t alloc_size, i;
3003c588192SMat Martineau 
3013c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3023c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3033c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3043c588192SMat Martineau 	 */
3053c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3063c588192SMat Martineau 
3073c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
3083c588192SMat Martineau 	if (!seq_list->list)
3093c588192SMat Martineau 		return -ENOMEM;
3103c588192SMat Martineau 
3113c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3123c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3133c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3143c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3153c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3163c588192SMat Martineau 
3173c588192SMat Martineau 	return 0;
3183c588192SMat Martineau }
3193c588192SMat Martineau 
3203c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3213c588192SMat Martineau {
3223c588192SMat Martineau 	kfree(seq_list->list);
3233c588192SMat Martineau }
3243c588192SMat Martineau 
3253c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3263c588192SMat Martineau 					   u16 seq)
3273c588192SMat Martineau {
3283c588192SMat Martineau 	/* Constant-time check for list membership */
3293c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3303c588192SMat Martineau }
3313c588192SMat Martineau 
3323c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
3333c588192SMat Martineau {
3343c588192SMat Martineau 	u16 mask = seq_list->mask;
3353c588192SMat Martineau 
3363c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
3373c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
3383c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
3393c588192SMat Martineau 	} else if (seq_list->head == seq) {
3403c588192SMat Martineau 		/* Head can be removed in constant time */
3413c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
3423c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3433c588192SMat Martineau 
3443c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3453c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3463c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3473c588192SMat Martineau 		}
3483c588192SMat Martineau 	} else {
3493c588192SMat Martineau 		/* Walk the list to find the sequence number */
3503c588192SMat Martineau 		u16 prev = seq_list->head;
3513c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3523c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3533c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3543c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3553c588192SMat Martineau 		}
3563c588192SMat Martineau 
3573c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3583c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3593c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3603c588192SMat Martineau 		if (seq_list->tail == seq)
3613c588192SMat Martineau 			seq_list->tail = prev;
3623c588192SMat Martineau 	}
3633c588192SMat Martineau 	return seq;
3643c588192SMat Martineau }
3653c588192SMat Martineau 
3663c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3673c588192SMat Martineau {
3683c588192SMat Martineau 	/* Remove the head in constant time */
3693c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3703c588192SMat Martineau }
3713c588192SMat Martineau 
3723c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3733c588192SMat Martineau {
3743c588192SMat Martineau 	u16 i;
375f522ae36SGustavo Padovan 
376f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
377f522ae36SGustavo Padovan 		return;
378f522ae36SGustavo Padovan 
3793c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3803c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3813c588192SMat Martineau 
3823c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3833c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3843c588192SMat Martineau }
3853c588192SMat Martineau 
3863c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3873c588192SMat Martineau {
3883c588192SMat Martineau 	u16 mask = seq_list->mask;
3893c588192SMat Martineau 
3903c588192SMat Martineau 	/* All appends happen in constant time */
3913c588192SMat Martineau 
392f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
393f522ae36SGustavo Padovan 		return;
394f522ae36SGustavo Padovan 
3953c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3963c588192SMat Martineau 		seq_list->head = seq;
3973c588192SMat Martineau 	else
3983c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3993c588192SMat Martineau 
4003c588192SMat Martineau 	seq_list->tail = seq;
4013c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4023c588192SMat Martineau }
4033c588192SMat Martineau 
404721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
405ab07801dSGustavo F. Padovan {
406721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
407721c4181SGustavo F. Padovan 					       chan_timer.work);
4083df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
409ab07801dSGustavo F. Padovan 	int reason;
410ab07801dSGustavo F. Padovan 
411e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
412ab07801dSGustavo F. Padovan 
4133df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4146be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
415ab07801dSGustavo F. Padovan 
41689bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
417ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
41889bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
419ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
420ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
421ab07801dSGustavo F. Padovan 	else
422ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
423ab07801dSGustavo F. Padovan 
4240f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
425ab07801dSGustavo F. Padovan 
4266be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
427ab07801dSGustavo F. Padovan 
42880b98027SGustavo Padovan 	chan->ops->close(chan);
4293df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4303df91ea2SAndrei Emeltchenko 
431371fd835SUlisses Furquim 	l2cap_chan_put(chan);
432ab07801dSGustavo F. Padovan }
433ab07801dSGustavo F. Padovan 
434eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4350a708f8fSGustavo F. Padovan {
43648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4370a708f8fSGustavo F. Padovan 
43848454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
43948454079SGustavo F. Padovan 	if (!chan)
44048454079SGustavo F. Padovan 		return NULL;
4410a708f8fSGustavo F. Padovan 
442c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
443c03b355eSAndrei Emeltchenko 
444333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
44523691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
446333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
44723691d75SGustavo F. Padovan 
448721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
449ab07801dSGustavo F. Padovan 
45089bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
45189bc500eSGustavo F. Padovan 
452144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
45371ba0e56SGustavo F. Padovan 
4542827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4552827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4562827011fSMat Martineau 
457eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
458abc545b8SSzymon Janc 
45948454079SGustavo F. Padovan 	return chan;
4600a708f8fSGustavo F. Padovan }
4610a708f8fSGustavo F. Padovan 
462144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4636ff5abbfSGustavo F. Padovan {
464144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
465144ad330SSyam Sidhardhan 
4664af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4674af66c69SJaganath Kanakkassery 
468333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46923691d75SGustavo F. Padovan 	list_del(&chan->global_l);
470333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
47123691d75SGustavo F. Padovan 
4724af66c69SJaganath Kanakkassery 	kfree(chan);
4736ff5abbfSGustavo F. Padovan }
4746ff5abbfSGustavo F. Padovan 
47530648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
47630648372SJaganath Kanakkassery {
477144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
47830648372SJaganath Kanakkassery 
479144ad330SSyam Sidhardhan 	kref_get(&c->kref);
48030648372SJaganath Kanakkassery }
48130648372SJaganath Kanakkassery 
48230648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
48330648372SJaganath Kanakkassery {
484144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
48530648372SJaganath Kanakkassery 
486144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
48730648372SJaganath Kanakkassery }
48830648372SJaganath Kanakkassery 
489bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
490bd4b1653SAndrei Emeltchenko {
491bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
492bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
493bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
494bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
495c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
496bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
497bd4b1653SAndrei Emeltchenko 
498bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
499bd4b1653SAndrei Emeltchenko }
500bd4b1653SAndrei Emeltchenko 
5010ce43ce6SJohan Hedberg static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
50238319713SJohan Hedberg {
5030ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5040ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5050ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
5060cd75f7eSJohan Hedberg 	chan->tx_credits = 0;
507f15b8ecfSJohan Hedberg 	chan->rx_credits = le_max_credits;
5083916aed8SJohan Hedberg 
5093916aed8SJohan Hedberg 	if (chan->imtu < L2CAP_LE_DEFAULT_MPS)
5103916aed8SJohan Hedberg 		chan->mps = chan->imtu;
5113916aed8SJohan Hedberg 	else
5123916aed8SJohan Hedberg 		chan->mps = L2CAP_LE_DEFAULT_MPS;
5130ce43ce6SJohan Hedberg 
5140ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
51538319713SJohan Hedberg }
51638319713SJohan Hedberg 
51793c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5180a708f8fSGustavo F. Padovan {
5190a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
520097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5210a708f8fSGustavo F. Padovan 
5229f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5230a708f8fSGustavo F. Padovan 
5248c1d787bSGustavo F. Padovan 	chan->conn = conn;
5250a708f8fSGustavo F. Padovan 
5265491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5275491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
528b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
529aeddd075SJohan Hedberg 			if (chan->dcid == L2CAP_CID_ATT) {
5306fcb06a2SAndre Guedes 				chan->omtu = L2CAP_DEFAULT_MTU;
531073d1cf3SJohan Hedberg 				chan->scid = L2CAP_CID_ATT;
532aeddd075SJohan Hedberg 			} else {
5339f22398cSJohan Hedberg 				chan->scid = l2cap_alloc_cid(conn);
534aeddd075SJohan Hedberg 			}
535b62f328bSVille Tervo 		} else {
5360a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
537fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
5380c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
539b62f328bSVille Tervo 		}
5405491120eSAndrei Emeltchenko 		break;
5415491120eSAndrei Emeltchenko 
5425491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5430a708f8fSGustavo F. Padovan 		/* Connectionless socket */
544fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
545fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5460c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5475491120eSAndrei Emeltchenko 		break;
5485491120eSAndrei Emeltchenko 
549416fa752SAndrei Emeltchenko 	case L2CAP_CHAN_CONN_FIX_A2MP:
550416fa752SAndrei Emeltchenko 		chan->scid = L2CAP_CID_A2MP;
551416fa752SAndrei Emeltchenko 		chan->dcid = L2CAP_CID_A2MP;
552416fa752SAndrei Emeltchenko 		chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
553416fa752SAndrei Emeltchenko 		chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
554416fa752SAndrei Emeltchenko 		break;
555416fa752SAndrei Emeltchenko 
5565491120eSAndrei Emeltchenko 	default:
5570a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
558fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
559fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5600c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5610a708f8fSGustavo F. Padovan 	}
5620a708f8fSGustavo F. Padovan 
5638f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5648f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5658f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5668f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5678f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5688936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5698f7975b1SAndrei Emeltchenko 
570371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
571baa7e1faSGustavo F. Padovan 
5725ee9891dSJohan Hedberg 	hci_conn_hold(conn->hcon);
5735ee9891dSJohan Hedberg 
5743df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
575643162a8SAndrei Emeltchenko }
576643162a8SAndrei Emeltchenko 
577466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
578643162a8SAndrei Emeltchenko {
579643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
580643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5813df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5820a708f8fSGustavo F. Padovan }
5830a708f8fSGustavo F. Padovan 
584466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5850a708f8fSGustavo F. Padovan {
5868c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5870a708f8fSGustavo F. Padovan 
588c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5890a708f8fSGustavo F. Padovan 
59049208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5910a708f8fSGustavo F. Padovan 
5920a708f8fSGustavo F. Padovan 	if (conn) {
59356f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
594baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5953df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5963d57dc68SGustavo F. Padovan 
597371fd835SUlisses Furquim 		l2cap_chan_put(chan);
598baa7e1faSGustavo F. Padovan 
5998c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6003cabbfdaSAndrei Emeltchenko 
6013cabbfdaSAndrei Emeltchenko 		if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
60276a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
60356f60984SAndrei Emeltchenko 
60456f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
60556f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6060a708f8fSGustavo F. Padovan 	}
6070a708f8fSGustavo F. Padovan 
608419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
609419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
610419e08c1SAndrei Emeltchenko 
611419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
612419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
613419e08c1SAndrei Emeltchenko 	}
614419e08c1SAndrei Emeltchenko 
615c0df7f6eSAndrei Emeltchenko 	chan->ops->teardown(chan, err);
6166be36555SAndrei Emeltchenko 
6172827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6186ff5abbfSGustavo F. Padovan 		return;
6192ead70b8SGustavo F. Padovan 
620ee556f66SGustavo Padovan 	switch(chan->mode) {
621ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
622ee556f66SGustavo Padovan 		break;
6230a708f8fSGustavo F. Padovan 
62438319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
625177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
62638319713SJohan Hedberg 		break;
62738319713SJohan Hedberg 
628ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6291a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6301a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6311a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6320a708f8fSGustavo F. Padovan 
633f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6340a708f8fSGustavo F. Padovan 
6353c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6363c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
637ee556f66SGustavo Padovan 
638ee556f66SGustavo Padovan 		/* fall through */
639ee556f66SGustavo Padovan 
640ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
641ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
642ee556f66SGustavo Padovan 		break;
6430a708f8fSGustavo F. Padovan 	}
644ee556f66SGustavo Padovan 
645ee556f66SGustavo Padovan 	return;
6460a708f8fSGustavo F. Padovan }
6470a708f8fSGustavo F. Padovan 
64827e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
64927e2d4c8SJohan Hedberg {
65027e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
65127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
65227e2d4c8SJohan Hedberg 	u16 result;
65327e2d4c8SJohan Hedberg 
65427e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
65527e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHORIZATION;
65627e2d4c8SJohan Hedberg 	else
65727e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
65827e2d4c8SJohan Hedberg 
65927e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
66027e2d4c8SJohan Hedberg 
66127e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
66227e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
6633916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
6640cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
66527e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
66627e2d4c8SJohan Hedberg 
66727e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
66827e2d4c8SJohan Hedberg 		       &rsp);
66927e2d4c8SJohan Hedberg }
67027e2d4c8SJohan Hedberg 
671791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
672791d60f7SJohan Hedberg {
673791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
674791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
675791d60f7SJohan Hedberg 	u16 result;
676791d60f7SJohan Hedberg 
677791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
678791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
679791d60f7SJohan Hedberg 	else
680791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
681791d60f7SJohan Hedberg 
682791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
683791d60f7SJohan Hedberg 
684791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
685791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
686791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
687791d60f7SJohan Hedberg 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
688791d60f7SJohan Hedberg 
689791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
690791d60f7SJohan Hedberg }
691791d60f7SJohan Hedberg 
6920f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
6934519de9aSGustavo F. Padovan {
6944519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6954519de9aSGustavo F. Padovan 
6967eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
6974519de9aSGustavo F. Padovan 
69889bc500eSGustavo F. Padovan 	switch (chan->state) {
6994519de9aSGustavo F. Padovan 	case BT_LISTEN:
700c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7014519de9aSGustavo F. Padovan 		break;
7024519de9aSGustavo F. Padovan 
7034519de9aSGustavo F. Padovan 	case BT_CONNECTED:
7044519de9aSGustavo F. Padovan 	case BT_CONFIG:
705cea04ce3SJohan Hedberg 		/* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
706cea04ce3SJohan Hedberg 		 * check for chan->psm.
707cea04ce3SJohan Hedberg 		 */
708cea04ce3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
7098d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7105e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
7114519de9aSGustavo F. Padovan 		} else
7124519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
7134519de9aSGustavo F. Padovan 		break;
7144519de9aSGustavo F. Padovan 
7154519de9aSGustavo F. Padovan 	case BT_CONNECT2:
716791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
717791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
718791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
71927e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
72027e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7214519de9aSGustavo F. Padovan 		}
7224519de9aSGustavo F. Padovan 
7234519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7244519de9aSGustavo F. Padovan 		break;
7254519de9aSGustavo F. Padovan 
7264519de9aSGustavo F. Padovan 	case BT_CONNECT:
7274519de9aSGustavo F. Padovan 	case BT_DISCONN:
7284519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7294519de9aSGustavo F. Padovan 		break;
7304519de9aSGustavo F. Padovan 
7314519de9aSGustavo F. Padovan 	default:
732c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7334519de9aSGustavo F. Padovan 		break;
7344519de9aSGustavo F. Padovan 	}
7354519de9aSGustavo F. Padovan }
7364519de9aSGustavo F. Padovan 
7374343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7380a708f8fSGustavo F. Padovan {
7396a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7406a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7414343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7420a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7430a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7440a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7450a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7460a708f8fSGustavo F. Padovan 		default:
7470a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7480a708f8fSGustavo F. Padovan 		}
7496a974b50SMarcel Holtmann 		break;
7503124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
7513124b843SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
7523124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7533124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7543124b843SMarcel Holtmann 		}
7553124b843SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH)
7563124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7573124b843SMarcel Holtmann 		else
7583124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7593124b843SMarcel Holtmann 		break;
7606a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
7616a974b50SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
7624343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7634343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
7640a708f8fSGustavo F. Padovan 
7654343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_HIGH)
7660a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
7670a708f8fSGustavo F. Padovan 			else
7680a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
7696a974b50SMarcel Holtmann 		}
7706a974b50SMarcel Holtmann 		/* fall through */
7716a974b50SMarcel Holtmann 	default:
7724343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7730a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7740a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
7750a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7760a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
7770a708f8fSGustavo F. Padovan 		default:
7780a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7790a708f8fSGustavo F. Padovan 		}
7806a974b50SMarcel Holtmann 		break;
7810a708f8fSGustavo F. Padovan 	}
7820a708f8fSGustavo F. Padovan }
7830a708f8fSGustavo F. Padovan 
7840a708f8fSGustavo F. Padovan /* Service level security */
785d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
7860a708f8fSGustavo F. Padovan {
7878c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7880a708f8fSGustavo F. Padovan 	__u8 auth_type;
7890a708f8fSGustavo F. Padovan 
790a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
791a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
792a17de2feSJohan Hedberg 
7934343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
7940a708f8fSGustavo F. Padovan 
7954343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
7960a708f8fSGustavo F. Padovan }
7970a708f8fSGustavo F. Padovan 
798b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
7990a708f8fSGustavo F. Padovan {
8000a708f8fSGustavo F. Padovan 	u8 id;
8010a708f8fSGustavo F. Padovan 
8020a708f8fSGustavo F. Padovan 	/* Get next available identificator.
8030a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
8040a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
8050a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
8060a708f8fSGustavo F. Padovan 	 */
8070a708f8fSGustavo F. Padovan 
808333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
8090a708f8fSGustavo F. Padovan 
8100a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
8110a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
8120a708f8fSGustavo F. Padovan 
8130a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
8140a708f8fSGustavo F. Padovan 
815333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
8160a708f8fSGustavo F. Padovan 
8170a708f8fSGustavo F. Padovan 	return id;
8180a708f8fSGustavo F. Padovan }
8190a708f8fSGustavo F. Padovan 
8202d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8212d792818SGustavo Padovan 			   void *data)
8220a708f8fSGustavo F. Padovan {
8230a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8240a708f8fSGustavo F. Padovan 	u8 flags;
8250a708f8fSGustavo F. Padovan 
8260a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8270a708f8fSGustavo F. Padovan 
8280a708f8fSGustavo F. Padovan 	if (!skb)
8290a708f8fSGustavo F. Padovan 		return;
8300a708f8fSGustavo F. Padovan 
8310a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
8320a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8330a708f8fSGustavo F. Padovan 	else
8340a708f8fSGustavo F. Padovan 		flags = ACL_START;
8350a708f8fSGustavo F. Padovan 
83614b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8375e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
83814b12d0bSJaikumar Ganesh 
83973d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8400a708f8fSGustavo F. Padovan }
8410a708f8fSGustavo F. Padovan 
84202b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
84302b0fbb9SMat Martineau {
84402b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
84502b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
84602b0fbb9SMat Martineau }
84702b0fbb9SMat Martineau 
84873d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
84973d80debSLuiz Augusto von Dentz {
85073d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
85173d80debSLuiz Augusto von Dentz 	u16 flags;
85273d80debSLuiz Augusto von Dentz 
85373d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
85473d80debSLuiz Augusto von Dentz 	       skb->priority);
85573d80debSLuiz Augusto von Dentz 
856d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
857d5f8a75dSMat Martineau 		if (chan->hs_hchan)
858d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
859d5f8a75dSMat Martineau 		else
860d5f8a75dSMat Martineau 			kfree_skb(skb);
861d5f8a75dSMat Martineau 
862d5f8a75dSMat Martineau 		return;
863d5f8a75dSMat Martineau 	}
864d5f8a75dSMat Martineau 
86573d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
86673d80debSLuiz Augusto von Dentz 	    lmp_no_flush_capable(hcon->hdev))
86773d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
86873d80debSLuiz Augusto von Dentz 	else
86973d80debSLuiz Augusto von Dentz 		flags = ACL_START;
87073d80debSLuiz Augusto von Dentz 
87173d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
87273d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
8730a708f8fSGustavo F. Padovan }
8740a708f8fSGustavo F. Padovan 
875b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
876b5c6aaedSMat Martineau {
877b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
878b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
879b5c6aaedSMat Martineau 
880b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
881b5c6aaedSMat Martineau 		/* S-Frame */
882b5c6aaedSMat Martineau 		control->sframe = 1;
883b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
884b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
885b5c6aaedSMat Martineau 
886b5c6aaedSMat Martineau 		control->sar = 0;
887b5c6aaedSMat Martineau 		control->txseq = 0;
888b5c6aaedSMat Martineau 	} else {
889b5c6aaedSMat Martineau 		/* I-Frame */
890b5c6aaedSMat Martineau 		control->sframe = 0;
891b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
892b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
893b5c6aaedSMat Martineau 
894b5c6aaedSMat Martineau 		control->poll = 0;
895b5c6aaedSMat Martineau 		control->super = 0;
896b5c6aaedSMat Martineau 	}
897b5c6aaedSMat Martineau }
898b5c6aaedSMat Martineau 
899b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
900b5c6aaedSMat Martineau {
901b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
902b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
903b5c6aaedSMat Martineau 
904b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
905b5c6aaedSMat Martineau 		/* S-Frame */
906b5c6aaedSMat Martineau 		control->sframe = 1;
907b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
908b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
909b5c6aaedSMat Martineau 
910b5c6aaedSMat Martineau 		control->sar = 0;
911b5c6aaedSMat Martineau 		control->txseq = 0;
912b5c6aaedSMat Martineau 	} else {
913b5c6aaedSMat Martineau 		/* I-Frame */
914b5c6aaedSMat Martineau 		control->sframe = 0;
915b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
916b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
917b5c6aaedSMat Martineau 
918b5c6aaedSMat Martineau 		control->poll = 0;
919b5c6aaedSMat Martineau 		control->super = 0;
920b5c6aaedSMat Martineau 	}
921b5c6aaedSMat Martineau }
922b5c6aaedSMat Martineau 
923b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
924b5c6aaedSMat Martineau 				    struct sk_buff *skb)
925b5c6aaedSMat Martineau {
926b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
927b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
928b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
929cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
930b5c6aaedSMat Martineau 	} else {
931b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
932b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
933cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
934b5c6aaedSMat Martineau 	}
935b5c6aaedSMat Martineau }
936b5c6aaedSMat Martineau 
937b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
938b5c6aaedSMat Martineau {
939b5c6aaedSMat Martineau 	u32 packed;
940b5c6aaedSMat Martineau 
941b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
942b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
943b5c6aaedSMat Martineau 
944b5c6aaedSMat Martineau 	if (control->sframe) {
945b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
946b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
947b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
948b5c6aaedSMat Martineau 	} else {
949b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
950b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
951b5c6aaedSMat Martineau 	}
952b5c6aaedSMat Martineau 
953b5c6aaedSMat Martineau 	return packed;
954b5c6aaedSMat Martineau }
955b5c6aaedSMat Martineau 
956b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
957b5c6aaedSMat Martineau {
958b5c6aaedSMat Martineau 	u16 packed;
959b5c6aaedSMat Martineau 
960b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
961b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
962b5c6aaedSMat Martineau 
963b5c6aaedSMat Martineau 	if (control->sframe) {
964b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
965b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
966b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
967b5c6aaedSMat Martineau 	} else {
968b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
969b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
970b5c6aaedSMat Martineau 	}
971b5c6aaedSMat Martineau 
972b5c6aaedSMat Martineau 	return packed;
973b5c6aaedSMat Martineau }
974b5c6aaedSMat Martineau 
975b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
976b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
977b5c6aaedSMat Martineau 				  struct sk_buff *skb)
978b5c6aaedSMat Martineau {
979b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
980b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
981b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
982b5c6aaedSMat Martineau 	} else {
983b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
984b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
985b5c6aaedSMat Martineau 	}
986b5c6aaedSMat Martineau }
987b5c6aaedSMat Martineau 
988ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
989ba7aa64fSGustavo Padovan {
990ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
991ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
992ba7aa64fSGustavo Padovan 	else
993ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
994ba7aa64fSGustavo Padovan }
995ba7aa64fSGustavo Padovan 
996a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
997a67d7f6fSMat Martineau 					       u32 control)
9980a708f8fSGustavo F. Padovan {
9990a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
10000a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1001ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
10020a708f8fSGustavo F. Padovan 
10030a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
100403a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
10050a708f8fSGustavo F. Padovan 
1006a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
10070a708f8fSGustavo F. Padovan 
10080a708f8fSGustavo F. Padovan 	if (!skb)
1009a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
10100a708f8fSGustavo F. Padovan 
10110a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
10120a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1013fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
101488843ab0SAndrei Emeltchenko 
1015a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1016a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1017a67d7f6fSMat Martineau 	else
1018a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10190a708f8fSGustavo F. Padovan 
102047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1021a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
102203a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10230a708f8fSGustavo F. Padovan 	}
10240a708f8fSGustavo F. Padovan 
102573d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1026a67d7f6fSMat Martineau 	return skb;
1027a67d7f6fSMat Martineau }
1028a67d7f6fSMat Martineau 
1029a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1030a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1031a67d7f6fSMat Martineau {
1032a67d7f6fSMat Martineau 	struct sk_buff *skb;
1033a67d7f6fSMat Martineau 	u32 control_field;
1034a67d7f6fSMat Martineau 
1035a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1036a67d7f6fSMat Martineau 
1037a67d7f6fSMat Martineau 	if (!control->sframe)
1038a67d7f6fSMat Martineau 		return;
1039a67d7f6fSMat Martineau 
1040b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1041b99e13adSMat Martineau 		return;
1042b99e13adSMat Martineau 
1043a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1044a67d7f6fSMat Martineau 	    !control->poll)
1045a67d7f6fSMat Martineau 		control->final = 1;
1046a67d7f6fSMat Martineau 
1047a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1048a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1049a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1050a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1051a67d7f6fSMat Martineau 
1052a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1053a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1054a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1055a67d7f6fSMat Martineau 	}
1056a67d7f6fSMat Martineau 
1057a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1058a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1059a67d7f6fSMat Martineau 
1060a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1061a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1062a67d7f6fSMat Martineau 	else
1063a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1064a67d7f6fSMat Martineau 
1065a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1066a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
106773d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
10680a708f8fSGustavo F. Padovan }
10690a708f8fSGustavo F. Padovan 
1070c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
10710a708f8fSGustavo F. Padovan {
1072c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
10730a708f8fSGustavo F. Padovan 
1074c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1075c9e3d5e0SMat Martineau 
1076c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1077c9e3d5e0SMat Martineau 	control.sframe = 1;
1078c9e3d5e0SMat Martineau 	control.poll = poll;
1079c9e3d5e0SMat Martineau 
1080c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1081c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1082c9e3d5e0SMat Martineau 	else
1083c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1084c9e3d5e0SMat Martineau 
1085c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1086c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
10870a708f8fSGustavo F. Padovan }
10880a708f8fSGustavo F. Padovan 
1089b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
10900a708f8fSGustavo F. Padovan {
1091c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
10920a708f8fSGustavo F. Padovan }
10930a708f8fSGustavo F. Padovan 
109493c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
109593c3e8f5SAndrei Emeltchenko {
109693c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
10971df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
10981df7b17aSMarcel Holtmann 	bool amp_available = false;
109993c3e8f5SAndrei Emeltchenko 
11001df7b17aSMarcel Holtmann 	if (!conn->hs_enabled)
11011df7b17aSMarcel Holtmann 		return false;
11021df7b17aSMarcel Holtmann 
11031df7b17aSMarcel Holtmann 	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
11041df7b17aSMarcel Holtmann 		return false;
11051df7b17aSMarcel Holtmann 
11061df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
11071df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
11081df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
11091df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
11101df7b17aSMarcel Holtmann 			amp_available = true;
11111df7b17aSMarcel Holtmann 			break;
11121df7b17aSMarcel Holtmann 		}
11131df7b17aSMarcel Holtmann 	}
11141df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
11151df7b17aSMarcel Holtmann 
11161df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11171df7b17aSMarcel Holtmann 		return amp_available;
1118848566b3SMarcel Holtmann 
111993c3e8f5SAndrei Emeltchenko 	return false;
112093c3e8f5SAndrei Emeltchenko }
112193c3e8f5SAndrei Emeltchenko 
11225ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11235ce66b59SAndrei Emeltchenko {
11245ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11255ce66b59SAndrei Emeltchenko 	return true;
11265ce66b59SAndrei Emeltchenko }
11275ce66b59SAndrei Emeltchenko 
11282766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11299b27f350SAndrei Emeltchenko {
11309b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11319b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11329b27f350SAndrei Emeltchenko 
11339b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11349b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11359b27f350SAndrei Emeltchenko 
11369b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11379b27f350SAndrei Emeltchenko 
11389b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11399b27f350SAndrei Emeltchenko 
11409b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11419b27f350SAndrei Emeltchenko }
11429b27f350SAndrei Emeltchenko 
11438eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11448eb200bdSMat Martineau {
11458eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11468eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11478eb200bdSMat Martineau 	req.psm  = chan->psm;
11488eb200bdSMat Martineau 	req.amp_id = amp_id;
11498eb200bdSMat Martineau 
11508eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
11518eb200bdSMat Martineau 
11528eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
11538eb200bdSMat Martineau 		       sizeof(req), &req);
11548eb200bdSMat Martineau }
11558eb200bdSMat Martineau 
115602b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
115702b0fbb9SMat Martineau {
115802b0fbb9SMat Martineau 	struct sk_buff *skb;
115902b0fbb9SMat Martineau 
116002b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
116102b0fbb9SMat Martineau 
116202b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
116302b0fbb9SMat Martineau 		return;
116402b0fbb9SMat Martineau 
116502b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
116602b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
116702b0fbb9SMat Martineau 	__clear_ack_timer(chan);
116802b0fbb9SMat Martineau 
116902b0fbb9SMat Martineau 	chan->retry_count = 0;
117002b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
117102b0fbb9SMat Martineau 		if (bt_cb(skb)->control.retries)
117202b0fbb9SMat Martineau 			bt_cb(skb)->control.retries = 1;
117302b0fbb9SMat Martineau 		else
117402b0fbb9SMat Martineau 			break;
117502b0fbb9SMat Martineau 	}
117602b0fbb9SMat Martineau 
117702b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
117802b0fbb9SMat Martineau 
117902b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
118002b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
118102b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
118202b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
118302b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
118402b0fbb9SMat Martineau 
118502b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
118602b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
118702b0fbb9SMat Martineau 
118802b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
118902b0fbb9SMat Martineau }
119002b0fbb9SMat Martineau 
11915f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
11925f3847a4SMat Martineau {
11935f3847a4SMat Martineau 	u8 move_role = chan->move_role;
11945f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
11955f3847a4SMat Martineau 
11965f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
11975f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
11985f3847a4SMat Martineau 
11995f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
12005f3847a4SMat Martineau 		return;
12015f3847a4SMat Martineau 
12025f3847a4SMat Martineau 	switch (move_role) {
12035f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
12045f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
12055f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
12065f3847a4SMat Martineau 		break;
12075f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
12085f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
12095f3847a4SMat Martineau 		break;
12105f3847a4SMat Martineau 	}
12115f3847a4SMat Martineau }
12125f3847a4SMat Martineau 
12139f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12149f0caeb1SVinicius Costa Gomes {
12152827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12169f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12179f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12189f0caeb1SVinicius Costa Gomes 
12190ce43ce6SJohan Hedberg 	if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits)
12200ce43ce6SJohan Hedberg 		chan->ops->suspend(chan);
1221177f8f2bSJohan Hedberg 
122254a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12239f0caeb1SVinicius Costa Gomes 
122454a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12259f0caeb1SVinicius Costa Gomes }
12269f0caeb1SVinicius Costa Gomes 
1227f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1228f1496deeSJohan Hedberg {
1229f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1230f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1231f1496deeSJohan Hedberg 
1232595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1233595177f3SJohan Hedberg 		return;
1234595177f3SJohan Hedberg 
1235f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1236f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1237f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
12383916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
12390cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1240f1496deeSJohan Hedberg 
1241f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1242f1496deeSJohan Hedberg 
1243f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1244f1496deeSJohan Hedberg 		       sizeof(req), &req);
1245f1496deeSJohan Hedberg }
1246f1496deeSJohan Hedberg 
1247f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1248f1496deeSJohan Hedberg {
1249f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1250f1496deeSJohan Hedberg 
1251f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1252f1496deeSJohan Hedberg 		return;
1253f1496deeSJohan Hedberg 
1254f1496deeSJohan Hedberg 	if (!chan->psm) {
1255f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1256f1496deeSJohan Hedberg 		return;
1257f1496deeSJohan Hedberg 	}
1258f1496deeSJohan Hedberg 
1259f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1260f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1261f1496deeSJohan Hedberg }
1262f1496deeSJohan Hedberg 
126393c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
126493c3e8f5SAndrei Emeltchenko {
126593c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
126693c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
126793c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1268f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1269f1496deeSJohan Hedberg 		l2cap_le_start(chan);
127093c3e8f5SAndrei Emeltchenko 	} else {
127193c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
127293c3e8f5SAndrei Emeltchenko 	}
127393c3e8f5SAndrei Emeltchenko }
127493c3e8f5SAndrei Emeltchenko 
1275fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
12760a708f8fSGustavo F. Padovan {
12778c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
12780a708f8fSGustavo F. Padovan 
12799f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
128096ac34fbSJohan Hedberg 		l2cap_le_start(chan);
12819f0caeb1SVinicius Costa Gomes 		return;
12829f0caeb1SVinicius Costa Gomes 	}
12839f0caeb1SVinicius Costa Gomes 
12840a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
12850a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
12860a708f8fSGustavo F. Padovan 			return;
12870a708f8fSGustavo F. Padovan 
1288d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
128993c3e8f5SAndrei Emeltchenko 		    __l2cap_no_conn_pending(chan)) {
129093c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
129193c3e8f5SAndrei Emeltchenko 		}
12920a708f8fSGustavo F. Padovan 	} else {
12930a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
1294ac73498cSAndrei Emeltchenko 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
12950a708f8fSGustavo F. Padovan 
12960a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
12970a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
12980a708f8fSGustavo F. Padovan 
1299ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
13000a708f8fSGustavo F. Padovan 
13012d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
13022d792818SGustavo Padovan 			       sizeof(req), &req);
13030a708f8fSGustavo F. Padovan 	}
13040a708f8fSGustavo F. Padovan }
13050a708f8fSGustavo F. Padovan 
13060a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
13070a708f8fSGustavo F. Padovan {
13080a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
13090a708f8fSGustavo F. Padovan 	if (!disable_ertm)
13100a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
13110a708f8fSGustavo F. Padovan 
13120a708f8fSGustavo F. Padovan 	switch (mode) {
13130a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
13140a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
13150a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
13160a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
13170a708f8fSGustavo F. Padovan 	default:
13180a708f8fSGustavo F. Padovan 		return 0x00;
13190a708f8fSGustavo F. Padovan 	}
13200a708f8fSGustavo F. Padovan }
13210a708f8fSGustavo F. Padovan 
13225e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
13230a708f8fSGustavo F. Padovan {
13245e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
13250a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
13260a708f8fSGustavo F. Padovan 
13270a708f8fSGustavo F. Padovan 	if (!conn)
13280a708f8fSGustavo F. Padovan 		return;
13290a708f8fSGustavo F. Padovan 
1330aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
13311a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
13321a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
13331a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
13340a708f8fSGustavo F. Padovan 	}
13350a708f8fSGustavo F. Padovan 
1336416fa752SAndrei Emeltchenko 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1337d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1338416fa752SAndrei Emeltchenko 		return;
1339416fa752SAndrei Emeltchenko 	}
1340416fa752SAndrei Emeltchenko 
1341fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1342fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
13432d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
13442d792818SGustavo Padovan 		       sizeof(req), &req);
13450a708f8fSGustavo F. Padovan 
1346f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
13470a708f8fSGustavo F. Padovan }
13480a708f8fSGustavo F. Padovan 
13490a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
13500a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
13510a708f8fSGustavo F. Padovan {
13523df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
13530a708f8fSGustavo F. Padovan 
13540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
13550a708f8fSGustavo F. Padovan 
13563df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13570a708f8fSGustavo F. Padovan 
13583df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
13596be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13600a708f8fSGustavo F. Padovan 
1361715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
13626be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
13630a708f8fSGustavo F. Padovan 			continue;
13640a708f8fSGustavo F. Padovan 		}
13650a708f8fSGustavo F. Padovan 
136689bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1367d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1368b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
13696be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13700a708f8fSGustavo F. Padovan 				continue;
13710a708f8fSGustavo F. Padovan 			}
13720a708f8fSGustavo F. Padovan 
1373c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1374c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1375c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
13760f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
13776be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13780a708f8fSGustavo F. Padovan 				continue;
13790a708f8fSGustavo F. Padovan 			}
13800a708f8fSGustavo F. Padovan 
138193c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
13820a708f8fSGustavo F. Padovan 
138389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
13840a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
13850a708f8fSGustavo F. Padovan 			char buf[128];
1386fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1387fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
13880a708f8fSGustavo F. Padovan 
1389d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
1390bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1391ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1392ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
13932dc4e510SGustavo Padovan 					chan->ops->defer(chan);
13940a708f8fSGustavo F. Padovan 
13950a708f8fSGustavo F. Padovan 				} else {
1396acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1397ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1398ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
13990a708f8fSGustavo F. Padovan 				}
14000a708f8fSGustavo F. Padovan 			} else {
1401ac73498cSAndrei Emeltchenko 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1402ac73498cSAndrei Emeltchenko 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
14030a708f8fSGustavo F. Padovan 			}
14040a708f8fSGustavo F. Padovan 
1405fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1406fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
14070a708f8fSGustavo F. Padovan 
1408c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
14090a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
14106be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14110a708f8fSGustavo F. Padovan 				continue;
14120a708f8fSGustavo F. Padovan 			}
14130a708f8fSGustavo F. Padovan 
1414c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
14150a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
141673ffa904SGustavo F. Padovan 				       l2cap_build_conf_req(chan, buf), buf);
141773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
14180a708f8fSGustavo F. Padovan 		}
14190a708f8fSGustavo F. Padovan 
14206be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
14210a708f8fSGustavo F. Padovan 	}
14220a708f8fSGustavo F. Padovan 
14233df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
14240a708f8fSGustavo F. Padovan }
14250a708f8fSGustavo F. Padovan 
1426c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1427b62f328bSVille Tervo  * Returns closest match, locked.
1428b62f328bSVille Tervo  */
1429d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1430c2287681SIdo Yariv 						    bdaddr_t *src,
1431c2287681SIdo Yariv 						    bdaddr_t *dst)
1432b62f328bSVille Tervo {
143323691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1434b62f328bSVille Tervo 
143523691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1436b62f328bSVille Tervo 
143723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
143889bc500eSGustavo F. Padovan 		if (state && c->state != state)
1439b62f328bSVille Tervo 			continue;
1440b62f328bSVille Tervo 
144123691d75SGustavo F. Padovan 		if (c->scid == cid) {
1442c2287681SIdo Yariv 			int src_match, dst_match;
1443c2287681SIdo Yariv 			int src_any, dst_any;
1444c2287681SIdo Yariv 
1445b62f328bSVille Tervo 			/* Exact match. */
14467eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
14477eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1448c2287681SIdo Yariv 			if (src_match && dst_match) {
144923691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
145023691d75SGustavo F. Padovan 				return c;
145123691d75SGustavo F. Padovan 			}
1452b62f328bSVille Tervo 
1453b62f328bSVille Tervo 			/* Closest match */
14547eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
14557eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1456c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1457c2287681SIdo Yariv 			    (src_any && dst_any))
145823691d75SGustavo F. Padovan 				c1 = c;
1459b62f328bSVille Tervo 		}
1460b62f328bSVille Tervo 	}
1461280f294fSGustavo F. Padovan 
146223691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1463b62f328bSVille Tervo 
146423691d75SGustavo F. Padovan 	return c1;
1465b62f328bSVille Tervo }
1466b62f328bSVille Tervo 
1467b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1468b62f328bSVille Tervo {
1469cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
147023691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1471cc8dba2bSMarcel Holtmann 	u8 dst_type;
1472b62f328bSVille Tervo 
1473b62f328bSVille Tervo 	BT_DBG("");
1474b62f328bSVille Tervo 
1475b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
1476073d1cf3SJohan Hedberg 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
1477cc8dba2bSMarcel Holtmann 					  &hcon->src, &hcon->dst);
147823691d75SGustavo F. Padovan 	if (!pchan)
1479b62f328bSVille Tervo 		return;
1480b62f328bSVille Tervo 
148144f3b0fbSJohan Hedberg 	/* Client ATT sockets should override the server one */
148244f3b0fbSJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
148344f3b0fbSJohan Hedberg 		return;
148444f3b0fbSJohan Hedberg 
1485cc8dba2bSMarcel Holtmann 	dst_type = bdaddr_type(hcon, hcon->dst_type);
1486cc8dba2bSMarcel Holtmann 
1487cc8dba2bSMarcel Holtmann 	/* If device is blocked, do not create a channel for it */
1488cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
1489cc8dba2bSMarcel Holtmann 		return;
1490cc8dba2bSMarcel Holtmann 
14918ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
149262f3a2cfSGustavo F. Padovan 
149380b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
149480808e43SGustavo F. Padovan 	if (!chan)
1495b62f328bSVille Tervo 		goto clean;
1496b62f328bSVille Tervo 
14979f22398cSJohan Hedberg 	chan->dcid = L2CAP_CID_ATT;
14989f22398cSJohan Hedberg 
1499cc8dba2bSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
1500cc8dba2bSMarcel Holtmann 	bacpy(&chan->dst, &hcon->dst);
1501cc8dba2bSMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
1502cc8dba2bSMarcel Holtmann 	chan->dst_type = dst_type;
1503b62f328bSVille Tervo 
150444f3b0fbSJohan Hedberg 	__l2cap_chan_add(conn, chan);
150548454079SGustavo F. Padovan 
1506b62f328bSVille Tervo clean:
15078ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
1508b62f328bSVille Tervo }
1509b62f328bSVille Tervo 
15100a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
15110a708f8fSGustavo F. Padovan {
151248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1513cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
15140a708f8fSGustavo F. Padovan 
15150a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15160a708f8fSGustavo F. Padovan 
1517d8729922SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1518d8729922SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1519d8729922SJohan Hedberg 	 */
1520cc110922SVinicius Costa Gomes 	if (hcon->out && hcon->type == LE_LINK)
1521cc110922SVinicius Costa Gomes 		smp_conn_security(hcon, hcon->pending_sec_level);
1522160dc6acSVinicius Costa Gomes 
15233df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15240a708f8fSGustavo F. Padovan 
152544f3b0fbSJohan Hedberg 	if (hcon->type == LE_LINK)
152644f3b0fbSJohan Hedberg 		l2cap_le_conn_ready(conn);
152744f3b0fbSJohan Hedberg 
15283df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1529baa7e1faSGustavo F. Padovan 
15306be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15310a708f8fSGustavo F. Padovan 
1532416fa752SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1533416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1534416fa752SAndrei Emeltchenko 			continue;
1535416fa752SAndrei Emeltchenko 		}
1536416fa752SAndrei Emeltchenko 
1537cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1538f1496deeSJohan Hedberg 			l2cap_le_start(chan);
153963128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
154074e75740SGustavo Padovan 			l2cap_chan_ready(chan);
1541b501d6a1SAnderson Briglia 
15421c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1543fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15441c244f79SGustavo Padovan 		}
15450a708f8fSGustavo F. Padovan 
15466be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15470a708f8fSGustavo F. Padovan 	}
15480a708f8fSGustavo F. Padovan 
15493df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15500a708f8fSGustavo F. Padovan }
15510a708f8fSGustavo F. Padovan 
15520a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15530a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15540a708f8fSGustavo F. Padovan {
155548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15560a708f8fSGustavo F. Padovan 
15570a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15580a708f8fSGustavo F. Padovan 
15593df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15600a708f8fSGustavo F. Padovan 
15613df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1562ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
15631d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
15640a708f8fSGustavo F. Padovan 	}
15650a708f8fSGustavo F. Padovan 
15663df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15670a708f8fSGustavo F. Padovan }
15680a708f8fSGustavo F. Padovan 
1569f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
15700a708f8fSGustavo F. Padovan {
1571f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1572030013d8SGustavo F. Padovan 					       info_timer.work);
15730a708f8fSGustavo F. Padovan 
15740a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
15750a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
15760a708f8fSGustavo F. Padovan 
15770a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
15780a708f8fSGustavo F. Padovan }
15790a708f8fSGustavo F. Padovan 
15802c8e1411SDavid Herrmann /*
15812c8e1411SDavid Herrmann  * l2cap_user
15822c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
15832c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
15842c8e1411SDavid Herrmann  * during unregistration.
15852c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
15862c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
15872c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
15882c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
15892c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
15902c8e1411SDavid Herrmann  * any time if they don't.
15912c8e1411SDavid Herrmann  */
15922c8e1411SDavid Herrmann 
15932c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
15942c8e1411SDavid Herrmann {
15952c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
15962c8e1411SDavid Herrmann 	int ret;
15972c8e1411SDavid Herrmann 
15982c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
15992c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
16002c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16012c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
16022c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
16032c8e1411SDavid Herrmann 	 * here, too. */
16042c8e1411SDavid Herrmann 
16052c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16062c8e1411SDavid Herrmann 
16072c8e1411SDavid Herrmann 	if (user->list.next || user->list.prev) {
16082c8e1411SDavid Herrmann 		ret = -EINVAL;
16092c8e1411SDavid Herrmann 		goto out_unlock;
16102c8e1411SDavid Herrmann 	}
16112c8e1411SDavid Herrmann 
16122c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
16132c8e1411SDavid Herrmann 	if (!conn->hchan) {
16142c8e1411SDavid Herrmann 		ret = -ENODEV;
16152c8e1411SDavid Herrmann 		goto out_unlock;
16162c8e1411SDavid Herrmann 	}
16172c8e1411SDavid Herrmann 
16182c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
16192c8e1411SDavid Herrmann 	if (ret)
16202c8e1411SDavid Herrmann 		goto out_unlock;
16212c8e1411SDavid Herrmann 
16222c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16232c8e1411SDavid Herrmann 	ret = 0;
16242c8e1411SDavid Herrmann 
16252c8e1411SDavid Herrmann out_unlock:
16262c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16272c8e1411SDavid Herrmann 	return ret;
16282c8e1411SDavid Herrmann }
16292c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16302c8e1411SDavid Herrmann 
16312c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16322c8e1411SDavid Herrmann {
16332c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16342c8e1411SDavid Herrmann 
16352c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16362c8e1411SDavid Herrmann 
16372c8e1411SDavid Herrmann 	if (!user->list.next || !user->list.prev)
16382c8e1411SDavid Herrmann 		goto out_unlock;
16392c8e1411SDavid Herrmann 
16402c8e1411SDavid Herrmann 	list_del(&user->list);
16412c8e1411SDavid Herrmann 	user->list.next = NULL;
16422c8e1411SDavid Herrmann 	user->list.prev = NULL;
16432c8e1411SDavid Herrmann 	user->remove(conn, user);
16442c8e1411SDavid Herrmann 
16452c8e1411SDavid Herrmann out_unlock:
16462c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16472c8e1411SDavid Herrmann }
16482c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16492c8e1411SDavid Herrmann 
16502c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16512c8e1411SDavid Herrmann {
16522c8e1411SDavid Herrmann 	struct l2cap_user *user;
16532c8e1411SDavid Herrmann 
16542c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16552c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
16562c8e1411SDavid Herrmann 		list_del(&user->list);
16572c8e1411SDavid Herrmann 		user->list.next = NULL;
16582c8e1411SDavid Herrmann 		user->list.prev = NULL;
16592c8e1411SDavid Herrmann 		user->remove(conn, user);
16602c8e1411SDavid Herrmann 	}
16612c8e1411SDavid Herrmann }
16622c8e1411SDavid Herrmann 
16635d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
16645d3de7dfSVinicius Costa Gomes {
16655d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
16665d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
16675d3de7dfSVinicius Costa Gomes 
16685d3de7dfSVinicius Costa Gomes 	if (!conn)
16695d3de7dfSVinicius Costa Gomes 		return;
16705d3de7dfSVinicius Costa Gomes 
16715d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
16725d3de7dfSVinicius Costa Gomes 
16735d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
16745d3de7dfSVinicius Costa Gomes 
16752c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
16762c8e1411SDavid Herrmann 
16773df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16783df91ea2SAndrei Emeltchenko 
16795d3de7dfSVinicius Costa Gomes 	/* Kill channels */
16805d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
168161d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
16826be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16836be36555SAndrei Emeltchenko 
16845d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
16856be36555SAndrei Emeltchenko 
16866be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16876be36555SAndrei Emeltchenko 
168880b98027SGustavo Padovan 		chan->ops->close(chan);
168961d6ef3eSMat Martineau 		l2cap_chan_put(chan);
16905d3de7dfSVinicius Costa Gomes 	}
16915d3de7dfSVinicius Costa Gomes 
16923df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16933df91ea2SAndrei Emeltchenko 
169473d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
169573d80debSLuiz Augusto von Dentz 
16965d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1697127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
16985d3de7dfSVinicius Costa Gomes 
169951a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1700127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
17018aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1702d26a2345SVinicius Costa Gomes 	}
17035d3de7dfSVinicius Costa Gomes 
17045d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
17059c903e37SDavid Herrmann 	conn->hchan = NULL;
17069c903e37SDavid Herrmann 	l2cap_conn_put(conn);
17075d3de7dfSVinicius Costa Gomes }
17085d3de7dfSVinicius Costa Gomes 
17096c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
17105d3de7dfSVinicius Costa Gomes {
17116c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
17126c9d42a1SGustavo F. Padovan 					       security_timer.work);
17135d3de7dfSVinicius Costa Gomes 
1714d06cc416SJohan Hedberg 	BT_DBG("conn %p", conn);
1715d06cc416SJohan Hedberg 
1716d06cc416SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1717d06cc416SJohan Hedberg 		smp_chan_destroy(conn);
17185d3de7dfSVinicius Costa Gomes 		l2cap_conn_del(conn->hcon, ETIMEDOUT);
17195d3de7dfSVinicius Costa Gomes 	}
1720d06cc416SJohan Hedberg }
17215d3de7dfSVinicius Costa Gomes 
1722baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
17230a708f8fSGustavo F. Padovan {
17240a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
172573d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
17260a708f8fSGustavo F. Padovan 
1727baf43251SClaudio Takahasi 	if (conn)
17280a708f8fSGustavo F. Padovan 		return conn;
17290a708f8fSGustavo F. Padovan 
173073d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
173173d80debSLuiz Augusto von Dentz 	if (!hchan)
17320a708f8fSGustavo F. Padovan 		return NULL;
17330a708f8fSGustavo F. Padovan 
17348bcde1f2SGustavo Padovan 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
173573d80debSLuiz Augusto von Dentz 	if (!conn) {
173673d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
173773d80debSLuiz Augusto von Dentz 		return NULL;
173873d80debSLuiz Augusto von Dentz 	}
173973d80debSLuiz Augusto von Dentz 
17409c903e37SDavid Herrmann 	kref_init(&conn->ref);
17410a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
17420a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
17439c903e37SDavid Herrmann 	hci_conn_get(conn->hcon);
174473d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
17450a708f8fSGustavo F. Padovan 
174673d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
17470a708f8fSGustavo F. Padovan 
1748dcc042d5SAndrei Emeltchenko 	switch (hcon->type) {
1749dcc042d5SAndrei Emeltchenko 	case LE_LINK:
1750dcc042d5SAndrei Emeltchenko 		if (hcon->hdev->le_mtu) {
1751acd7d370SVille Tervo 			conn->mtu = hcon->hdev->le_mtu;
1752dcc042d5SAndrei Emeltchenko 			break;
1753dcc042d5SAndrei Emeltchenko 		}
1754dcc042d5SAndrei Emeltchenko 		/* fall through */
1755dcc042d5SAndrei Emeltchenko 	default:
17560a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1757dcc042d5SAndrei Emeltchenko 		break;
1758dcc042d5SAndrei Emeltchenko 	}
1759acd7d370SVille Tervo 
17600a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
17610a708f8fSGustavo F. Padovan 
1762848566b3SMarcel Holtmann 	if (hcon->type == ACL_LINK)
1763848566b3SMarcel Holtmann 		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
1764848566b3SMarcel Holtmann 					    &hcon->hdev->dev_flags);
1765848566b3SMarcel Holtmann 
17660a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
17673df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1768baa7e1faSGustavo F. Padovan 
1769baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
17702c8e1411SDavid Herrmann 	INIT_LIST_HEAD(&conn->users);
17710a708f8fSGustavo F. Padovan 
17725d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
17736c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
17745d3de7dfSVinicius Costa Gomes 	else
1775030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
17760a708f8fSGustavo F. Padovan 
17779f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
17780a708f8fSGustavo F. Padovan 
17790a708f8fSGustavo F. Padovan 	return conn;
17800a708f8fSGustavo F. Padovan }
17810a708f8fSGustavo F. Padovan 
17829c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17839c903e37SDavid Herrmann {
17849c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17859c903e37SDavid Herrmann 
17869c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17879c903e37SDavid Herrmann 	kfree(conn);
17889c903e37SDavid Herrmann }
17899c903e37SDavid Herrmann 
17909c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn)
17919c903e37SDavid Herrmann {
17929c903e37SDavid Herrmann 	kref_get(&conn->ref);
17939c903e37SDavid Herrmann }
17949c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
17959c903e37SDavid Herrmann 
17969c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
17979c903e37SDavid Herrmann {
17989c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
17999c903e37SDavid Herrmann }
18009c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
18019c903e37SDavid Herrmann 
18020a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
18030a708f8fSGustavo F. Padovan 
1804c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
18050a708f8fSGustavo F. Padovan  * Returns closest match.
18060a708f8fSGustavo F. Padovan  */
1807c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1808c2287681SIdo Yariv 						   bdaddr_t *src,
1809bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1810bf20fd4eSJohan Hedberg 						   u8 link_type)
18110a708f8fSGustavo F. Padovan {
181223691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
18130a708f8fSGustavo F. Padovan 
181423691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
18150a708f8fSGustavo F. Padovan 
181623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
181789bc500eSGustavo F. Padovan 		if (state && c->state != state)
18180a708f8fSGustavo F. Padovan 			continue;
18190a708f8fSGustavo F. Padovan 
1820bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1821bf20fd4eSJohan Hedberg 			continue;
1822bf20fd4eSJohan Hedberg 
1823bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1824bf20fd4eSJohan Hedberg 			continue;
1825bf20fd4eSJohan Hedberg 
182623691d75SGustavo F. Padovan 		if (c->psm == psm) {
1827c2287681SIdo Yariv 			int src_match, dst_match;
1828c2287681SIdo Yariv 			int src_any, dst_any;
1829c2287681SIdo Yariv 
18300a708f8fSGustavo F. Padovan 			/* Exact match. */
18317eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18327eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1833c2287681SIdo Yariv 			if (src_match && dst_match) {
1834a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
183523691d75SGustavo F. Padovan 				return c;
183623691d75SGustavo F. Padovan 			}
18370a708f8fSGustavo F. Padovan 
18380a708f8fSGustavo F. Padovan 			/* Closest match */
18397eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18407eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1841c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1842c2287681SIdo Yariv 			    (src_any && dst_any))
184323691d75SGustavo F. Padovan 				c1 = c;
18440a708f8fSGustavo F. Padovan 		}
18450a708f8fSGustavo F. Padovan 	}
18460a708f8fSGustavo F. Padovan 
184723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18480a708f8fSGustavo F. Padovan 
184923691d75SGustavo F. Padovan 	return c1;
18500a708f8fSGustavo F. Padovan }
18510a708f8fSGustavo F. Padovan 
18524946096dSJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type)
18534946096dSJohan Hedberg {
18544946096dSJohan Hedberg 	if (!psm)
18554946096dSJohan Hedberg 		return false;
18564946096dSJohan Hedberg 
18574946096dSJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
18584946096dSJohan Hedberg 		return (psm < 0x00ff);
18594946096dSJohan Hedberg 
18604946096dSJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
18614946096dSJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
18624946096dSJohan Hedberg }
18634946096dSJohan Hedberg 
18648e9f9892SAndre Guedes int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
18658e9f9892SAndre Guedes 		       bdaddr_t *dst, u8 dst_type)
18660a708f8fSGustavo F. Padovan {
18670a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
18680a708f8fSGustavo F. Padovan 	struct hci_conn *hcon;
18690a708f8fSGustavo F. Padovan 	struct hci_dev *hdev;
18700a708f8fSGustavo F. Padovan 	__u8 auth_type;
18710a708f8fSGustavo F. Padovan 	int err;
18720a708f8fSGustavo F. Padovan 
18737eafc59eSMarcel Holtmann 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
1874ab19516aSSyam Sidhardhan 	       dst_type, __le16_to_cpu(psm));
18750a708f8fSGustavo F. Padovan 
18767eafc59eSMarcel Holtmann 	hdev = hci_get_route(dst, &chan->src);
18770a708f8fSGustavo F. Padovan 	if (!hdev)
18780a708f8fSGustavo F. Padovan 		return -EHOSTUNREACH;
18790a708f8fSGustavo F. Padovan 
188009fd0de5SGustavo F. Padovan 	hci_dev_lock(hdev);
18810a708f8fSGustavo F. Padovan 
18826be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
188303a00194SGustavo F. Padovan 
18844946096dSJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
188503a00194SGustavo F. Padovan 	    chan->chan_type != L2CAP_CHAN_RAW) {
188603a00194SGustavo F. Padovan 		err = -EINVAL;
188703a00194SGustavo F. Padovan 		goto done;
188803a00194SGustavo F. Padovan 	}
188903a00194SGustavo F. Padovan 
189003a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
189103a00194SGustavo F. Padovan 		err = -EINVAL;
189203a00194SGustavo F. Padovan 		goto done;
189303a00194SGustavo F. Padovan 	}
189403a00194SGustavo F. Padovan 
189503a00194SGustavo F. Padovan 	switch (chan->mode) {
189603a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
18970ce43ce6SJohan Hedberg 		break;
189838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
18990ce43ce6SJohan Hedberg 		l2cap_le_flowctl_init(chan);
190003a00194SGustavo F. Padovan 		break;
190103a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
190203a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
190303a00194SGustavo F. Padovan 		if (!disable_ertm)
190403a00194SGustavo F. Padovan 			break;
190503a00194SGustavo F. Padovan 		/* fall through */
190603a00194SGustavo F. Padovan 	default:
190703a00194SGustavo F. Padovan 		err = -ENOTSUPP;
190803a00194SGustavo F. Padovan 		goto done;
190903a00194SGustavo F. Padovan 	}
191003a00194SGustavo F. Padovan 
19110797e01dSGustavo Padovan 	switch (chan->state) {
191203a00194SGustavo F. Padovan 	case BT_CONNECT:
191303a00194SGustavo F. Padovan 	case BT_CONNECT2:
191403a00194SGustavo F. Padovan 	case BT_CONFIG:
191503a00194SGustavo F. Padovan 		/* Already connecting */
191603a00194SGustavo F. Padovan 		err = 0;
191703a00194SGustavo F. Padovan 		goto done;
191803a00194SGustavo F. Padovan 
191903a00194SGustavo F. Padovan 	case BT_CONNECTED:
192003a00194SGustavo F. Padovan 		/* Already connected */
192103a00194SGustavo F. Padovan 		err = -EISCONN;
192203a00194SGustavo F. Padovan 		goto done;
192303a00194SGustavo F. Padovan 
192403a00194SGustavo F. Padovan 	case BT_OPEN:
192503a00194SGustavo F. Padovan 	case BT_BOUND:
192603a00194SGustavo F. Padovan 		/* Can connect */
192703a00194SGustavo F. Padovan 		break;
192803a00194SGustavo F. Padovan 
192903a00194SGustavo F. Padovan 	default:
193003a00194SGustavo F. Padovan 		err = -EBADFD;
193103a00194SGustavo F. Padovan 		goto done;
193203a00194SGustavo F. Padovan 	}
193303a00194SGustavo F. Padovan 
193403a00194SGustavo F. Padovan 	/* Set destination address and psm */
19357eafc59eSMarcel Holtmann 	bacpy(&chan->dst, dst);
19364f1654e0SMarcel Holtmann 	chan->dst_type = dst_type;
19376be36555SAndrei Emeltchenko 
193803a00194SGustavo F. Padovan 	chan->psm = psm;
193903a00194SGustavo F. Padovan 	chan->dcid = cid;
19400a708f8fSGustavo F. Padovan 
19414343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
19420a708f8fSGustavo F. Padovan 
1943f224ca5fSJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
19448e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
19454343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1946acd7d370SVille Tervo 	else
19478e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
19484343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1949acd7d370SVille Tervo 
195030e76272SVille Tervo 	if (IS_ERR(hcon)) {
195130e76272SVille Tervo 		err = PTR_ERR(hcon);
19520a708f8fSGustavo F. Padovan 		goto done;
195330e76272SVille Tervo 	}
19540a708f8fSGustavo F. Padovan 
1955baf43251SClaudio Takahasi 	conn = l2cap_conn_add(hcon);
19560a708f8fSGustavo F. Padovan 	if (!conn) {
195776a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
195830e76272SVille Tervo 		err = -ENOMEM;
19590a708f8fSGustavo F. Padovan 		goto done;
19600a708f8fSGustavo F. Padovan 	}
19610a708f8fSGustavo F. Padovan 
1962141d5706SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
196376a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
1964141d5706SJohan Hedberg 		err = -EBUSY;
19659f0caeb1SVinicius Costa Gomes 		goto done;
19669f0caeb1SVinicius Costa Gomes 	}
19679f0caeb1SVinicius Costa Gomes 
19680a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
19697eafc59eSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
19704f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
19710a708f8fSGustavo F. Padovan 
19726be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
197348454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
19746be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
197548454079SGustavo F. Padovan 
19765ee9891dSJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
19775ee9891dSJohan Hedberg 	hci_conn_drop(hcon);
19785ee9891dSJohan Hedberg 
19796be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
19808d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
19810a708f8fSGustavo F. Padovan 
19820a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1983715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1984c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1985d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
19866be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
19870a708f8fSGustavo F. Padovan 		} else
1988fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
19890a708f8fSGustavo F. Padovan 	}
19900a708f8fSGustavo F. Padovan 
199130e76272SVille Tervo 	err = 0;
199230e76272SVille Tervo 
19930a708f8fSGustavo F. Padovan done:
19946be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
199509fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
19960a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
19970a708f8fSGustavo F. Padovan 	return err;
19980a708f8fSGustavo F. Padovan }
19990a708f8fSGustavo F. Padovan 
2000721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
20010a708f8fSGustavo F. Padovan {
2002721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2003721c4181SGustavo F. Padovan 					       monitor_timer.work);
20040a708f8fSGustavo F. Padovan 
2005525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
20060a708f8fSGustavo F. Padovan 
20076be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20086be36555SAndrei Emeltchenko 
200980909e04SMat Martineau 	if (!chan->conn) {
20106be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
20118d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
20120a708f8fSGustavo F. Padovan 		return;
20130a708f8fSGustavo F. Padovan 	}
20140a708f8fSGustavo F. Padovan 
2015401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
20160a708f8fSGustavo F. Padovan 
20176be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20188d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20190a708f8fSGustavo F. Padovan }
20200a708f8fSGustavo F. Padovan 
2021721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20220a708f8fSGustavo F. Padovan {
2023721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2024721c4181SGustavo F. Padovan 					       retrans_timer.work);
20250a708f8fSGustavo F. Padovan 
202649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20270a708f8fSGustavo F. Padovan 
20286be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20296be36555SAndrei Emeltchenko 
203080909e04SMat Martineau 	if (!chan->conn) {
203180909e04SMat Martineau 		l2cap_chan_unlock(chan);
203280909e04SMat Martineau 		l2cap_chan_put(chan);
203380909e04SMat Martineau 		return;
203480909e04SMat Martineau 	}
20350a708f8fSGustavo F. Padovan 
2036401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20376be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20388d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20390a708f8fSGustavo F. Padovan }
20400a708f8fSGustavo F. Padovan 
2041d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20423733937dSMat Martineau 				 struct sk_buff_head *skbs)
20430a708f8fSGustavo F. Padovan {
20440a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20453733937dSMat Martineau 	struct l2cap_ctrl *control;
20460a708f8fSGustavo F. Padovan 
20473733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20483733937dSMat Martineau 
2049b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2050b99e13adSMat Martineau 		return;
2051b99e13adSMat Martineau 
20523733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20533733937dSMat Martineau 
20543733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20553733937dSMat Martineau 
20563733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20573733937dSMat Martineau 
20583733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
20593733937dSMat Martineau 		control = &bt_cb(skb)->control;
20603733937dSMat Martineau 
20613733937dSMat Martineau 		control->reqseq = 0;
20623733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20633733937dSMat Martineau 
20643733937dSMat Martineau 		__pack_control(chan, control, skb);
20650a708f8fSGustavo F. Padovan 
206647d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20673733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20683733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20690a708f8fSGustavo F. Padovan 		}
20700a708f8fSGustavo F. Padovan 
20714343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20720a708f8fSGustavo F. Padovan 
2073b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20743733937dSMat Martineau 
2075836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20763733937dSMat Martineau 		chan->frames_sent++;
20770a708f8fSGustavo F. Padovan 	}
20780a708f8fSGustavo F. Padovan }
20790a708f8fSGustavo F. Padovan 
208067c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20810a708f8fSGustavo F. Padovan {
20820a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
208318a48e76SMat Martineau 	struct l2cap_ctrl *control;
208418a48e76SMat Martineau 	int sent = 0;
208518a48e76SMat Martineau 
208618a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20870a708f8fSGustavo F. Padovan 
208889bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20890a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20900a708f8fSGustavo F. Padovan 
209194122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
209294122bbeSMat Martineau 		return 0;
209394122bbeSMat Martineau 
2094b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2095b99e13adSMat Martineau 		return 0;
2096b99e13adSMat Martineau 
209718a48e76SMat Martineau 	while (chan->tx_send_head &&
209818a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
209918a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
21000a708f8fSGustavo F. Padovan 
210118a48e76SMat Martineau 		skb = chan->tx_send_head;
21020a708f8fSGustavo F. Padovan 
210318a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
210418a48e76SMat Martineau 		control = &bt_cb(skb)->control;
21050a708f8fSGustavo F. Padovan 
2106e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
210718a48e76SMat Martineau 			control->final = 1;
2108e2ab4353SGustavo F. Padovan 
210918a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
211018a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
211118a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
21120a708f8fSGustavo F. Padovan 
211318a48e76SMat Martineau 		__pack_control(chan, control, skb);
21140a708f8fSGustavo F. Padovan 
211547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
211618a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
211718a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
21180a708f8fSGustavo F. Padovan 		}
21190a708f8fSGustavo F. Padovan 
212018a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
212118a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
212218a48e76SMat Martineau 		 */
212318a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
212418a48e76SMat Martineau 
212518a48e76SMat Martineau 		if (!tx_skb)
212618a48e76SMat Martineau 			break;
21270a708f8fSGustavo F. Padovan 
21281a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21290a708f8fSGustavo F. Padovan 
2130836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21316a026610SGustavo F. Padovan 		chan->unacked_frames++;
21326a026610SGustavo F. Padovan 		chan->frames_sent++;
213318a48e76SMat Martineau 		sent++;
21340a708f8fSGustavo F. Padovan 
213558d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
213658d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21370a708f8fSGustavo F. Padovan 		else
213858d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
213918a48e76SMat Martineau 
214018a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2141b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21420a708f8fSGustavo F. Padovan 	}
21430a708f8fSGustavo F. Padovan 
2144b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2145b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
214618a48e76SMat Martineau 
214718a48e76SMat Martineau 	return sent;
21480a708f8fSGustavo F. Padovan }
21490a708f8fSGustavo F. Padovan 
2150e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2151e1fbd4c1SMat Martineau {
2152e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2153e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2154e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2155e1fbd4c1SMat Martineau 	u16 seq;
2156e1fbd4c1SMat Martineau 
2157e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2158e1fbd4c1SMat Martineau 
2159e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2160e1fbd4c1SMat Martineau 		return;
2161e1fbd4c1SMat Martineau 
2162b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2163b99e13adSMat Martineau 		return;
2164b99e13adSMat Martineau 
2165e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2166e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2167e1fbd4c1SMat Martineau 
2168e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2169e1fbd4c1SMat Martineau 		if (!skb) {
2170e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2171e1fbd4c1SMat Martineau 			       seq);
2172e1fbd4c1SMat Martineau 			continue;
2173e1fbd4c1SMat Martineau 		}
2174e1fbd4c1SMat Martineau 
2175e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
2176e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
2177e1fbd4c1SMat Martineau 
2178e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2179e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
2180e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21815e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2182e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2183e1fbd4c1SMat Martineau 			break;
2184e1fbd4c1SMat Martineau 		}
2185e1fbd4c1SMat Martineau 
2186e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2187e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2188e1fbd4c1SMat Martineau 			control.final = 1;
2189e1fbd4c1SMat Martineau 		else
2190e1fbd4c1SMat Martineau 			control.final = 0;
2191e1fbd4c1SMat Martineau 
2192e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2193e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2194e1fbd4c1SMat Martineau 			 * writeable copy
2195e1fbd4c1SMat Martineau 			 */
21968bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2197e1fbd4c1SMat Martineau 		} else {
21988bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2199e1fbd4c1SMat Martineau 		}
2200e1fbd4c1SMat Martineau 
2201e1fbd4c1SMat Martineau 		if (!tx_skb) {
2202e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2203e1fbd4c1SMat Martineau 			break;
2204e1fbd4c1SMat Martineau 		}
2205e1fbd4c1SMat Martineau 
2206e1fbd4c1SMat Martineau 		/* Update skb contents */
2207e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2208e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2209e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2210e1fbd4c1SMat Martineau 		} else {
2211e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2212e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2213e1fbd4c1SMat Martineau 		}
2214e1fbd4c1SMat Martineau 
2215e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
2216e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
2217e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
2218e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
2219e1fbd4c1SMat Martineau 		}
2220e1fbd4c1SMat Martineau 
2221e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2222e1fbd4c1SMat Martineau 
2223e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2224e1fbd4c1SMat Martineau 
2225e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2226e1fbd4c1SMat Martineau 	}
2227e1fbd4c1SMat Martineau }
2228e1fbd4c1SMat Martineau 
2229f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2230f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2231f80842a8SMat Martineau {
2232f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2233f80842a8SMat Martineau 
2234f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2235f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2236f80842a8SMat Martineau }
2237f80842a8SMat Martineau 
2238d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2239d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2240d2a7ac5dSMat Martineau {
2241e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2242e1fbd4c1SMat Martineau 
2243e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2244e1fbd4c1SMat Martineau 
2245e1fbd4c1SMat Martineau 	if (control->poll)
2246e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2247e1fbd4c1SMat Martineau 
2248e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2249e1fbd4c1SMat Martineau 
2250e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2251e1fbd4c1SMat Martineau 		return;
2252e1fbd4c1SMat Martineau 
2253e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2254e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2255e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
2256e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2257e1fbd4c1SMat Martineau 				break;
2258e1fbd4c1SMat Martineau 		}
2259e1fbd4c1SMat Martineau 
2260e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2261e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2262e1fbd4c1SMat Martineau 				break;
2263e1fbd4c1SMat Martineau 
2264e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2265e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
2266e1fbd4c1SMat Martineau 		}
2267e1fbd4c1SMat Martineau 
2268e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2269e1fbd4c1SMat Martineau 	}
2270d2a7ac5dSMat Martineau }
2271d2a7ac5dSMat Martineau 
2272b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2273b17e73bbSSzymon Janc {
22740a0aba42SMat Martineau 	struct l2cap_ctrl control;
22750a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22760a0aba42SMat Martineau 					 chan->last_acked_seq);
22770a0aba42SMat Martineau 	int threshold;
22780a0aba42SMat Martineau 
22790a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22800a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22810a0aba42SMat Martineau 
22820a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22830a0aba42SMat Martineau 	control.sframe = 1;
22840a0aba42SMat Martineau 
22850a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22860a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2287b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22880a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22890a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22900a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22910a0aba42SMat Martineau 	} else {
22920a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22930a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22940a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22950a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22960a0aba42SMat Martineau 				frames_to_ack = 0;
22970a0aba42SMat Martineau 		}
22980a0aba42SMat Martineau 
2299c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
23000a0aba42SMat Martineau 		 * Calculate without mul or div
23010a0aba42SMat Martineau 		 */
2302c20f8e35SMat Martineau 		threshold = chan->ack_win;
23030a0aba42SMat Martineau 		threshold += threshold << 1;
23040a0aba42SMat Martineau 		threshold >>= 2;
23050a0aba42SMat Martineau 
2306b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
23070a0aba42SMat Martineau 		       threshold);
23080a0aba42SMat Martineau 
23090a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
23100a0aba42SMat Martineau 			__clear_ack_timer(chan);
23110a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
23120a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
23130a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
23140a0aba42SMat Martineau 			frames_to_ack = 0;
23150a0aba42SMat Martineau 		}
23160a0aba42SMat Martineau 
23170a0aba42SMat Martineau 		if (frames_to_ack)
23180a0aba42SMat Martineau 			__set_ack_timer(chan);
23190a0aba42SMat Martineau 	}
2320b17e73bbSSzymon Janc }
2321b17e73bbSSzymon Janc 
232204124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
232304124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
232404124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23250a708f8fSGustavo F. Padovan {
23260952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23270a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
232890338947SGustavo Padovan 	int sent = 0;
23290a708f8fSGustavo F. Padovan 
23300a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
23310a708f8fSGustavo F. Padovan 		return -EFAULT;
23320a708f8fSGustavo F. Padovan 
23330a708f8fSGustavo F. Padovan 	sent += count;
23340a708f8fSGustavo F. Padovan 	len  -= count;
23350a708f8fSGustavo F. Padovan 
23360a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23370a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23380a708f8fSGustavo F. Padovan 	while (len) {
2339fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2340fbe00700SGustavo Padovan 
23410a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23420a708f8fSGustavo F. Padovan 
2343fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
234490338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2345fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2346fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23472f7719ceSAndrei Emeltchenko 
2348fbe00700SGustavo Padovan 		*frag = tmp;
2349fbe00700SGustavo Padovan 
23500a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
23510a708f8fSGustavo F. Padovan 			return -EFAULT;
23520a708f8fSGustavo F. Padovan 
23535e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
23545e59b791SLuiz Augusto von Dentz 
23550a708f8fSGustavo F. Padovan 		sent += count;
23560a708f8fSGustavo F. Padovan 		len  -= count;
23570a708f8fSGustavo F. Padovan 
23582d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23592d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23602d0ed3d5SGustavo Padovan 
23610a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23620a708f8fSGustavo F. Padovan 	}
23630a708f8fSGustavo F. Padovan 
23640a708f8fSGustavo F. Padovan 	return sent;
23650a708f8fSGustavo F. Padovan }
23660a708f8fSGustavo F. Padovan 
23675e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23685e59b791SLuiz Augusto von Dentz 						 struct msghdr *msg, size_t len,
23695e59b791SLuiz Augusto von Dentz 						 u32 priority)
23700a708f8fSGustavo F. Padovan {
23718c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23720a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
237303a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23740a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23750a708f8fSGustavo F. Padovan 
237643b1b8dfSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
237743b1b8dfSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len, priority);
23780a708f8fSGustavo F. Padovan 
23790a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23802f7719ceSAndrei Emeltchenko 
23812f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
238290338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
238390338947SGustavo Padovan 	if (IS_ERR(skb))
238490338947SGustavo Padovan 		return skb;
23850a708f8fSGustavo F. Padovan 
23865e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23875e59b791SLuiz Augusto von Dentz 
23880a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23890a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2390fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2391daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
239243b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23930a708f8fSGustavo F. Padovan 
23940952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23950a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23960a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23970a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23980a708f8fSGustavo F. Padovan 	}
23990a708f8fSGustavo F. Padovan 	return skb;
24000a708f8fSGustavo F. Padovan }
24010a708f8fSGustavo F. Padovan 
24025e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
24035e59b791SLuiz Augusto von Dentz 					      struct msghdr *msg, size_t len,
24045e59b791SLuiz Augusto von Dentz 					      u32 priority)
24050a708f8fSGustavo F. Padovan {
24068c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24070a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2408f2ba7faeSGustavo Padovan 	int err, count;
24090a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24100a708f8fSGustavo F. Padovan 
2411b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24120a708f8fSGustavo F. Padovan 
2413f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
24142f7719ceSAndrei Emeltchenko 
2415f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
241690338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
241790338947SGustavo Padovan 	if (IS_ERR(skb))
241890338947SGustavo Padovan 		return skb;
24190a708f8fSGustavo F. Padovan 
24205e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
24215e59b791SLuiz Augusto von Dentz 
24220a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24230a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2424fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24256ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24260a708f8fSGustavo F. Padovan 
24270952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24280a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24290a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24300a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24310a708f8fSGustavo F. Padovan 	}
24320a708f8fSGustavo F. Padovan 	return skb;
24330a708f8fSGustavo F. Padovan }
24340a708f8fSGustavo F. Padovan 
2435ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2436ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
243794122bbeSMat Martineau 					       u16 sdulen)
24380a708f8fSGustavo F. Padovan {
24398c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24400a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2441e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24420a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24430a708f8fSGustavo F. Padovan 
2444b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24450a708f8fSGustavo F. Padovan 
24460a708f8fSGustavo F. Padovan 	if (!conn)
24470a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24480a708f8fSGustavo F. Padovan 
2449ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2450e4ca6d98SAndrei Emeltchenko 
24510a708f8fSGustavo F. Padovan 	if (sdulen)
245203a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24530a708f8fSGustavo F. Padovan 
245447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
245503a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24560a708f8fSGustavo F. Padovan 
24570a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24582f7719ceSAndrei Emeltchenko 
24592f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
246090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
246190338947SGustavo Padovan 	if (IS_ERR(skb))
246290338947SGustavo Padovan 		return skb;
24630a708f8fSGustavo F. Padovan 
24640a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24650a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2466fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24670a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
246888843ab0SAndrei Emeltchenko 
246918a48e76SMat Martineau 	/* Control header is populated later */
247018a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
247118a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
247218a48e76SMat Martineau 	else
247318a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
247488843ab0SAndrei Emeltchenko 
24750a708f8fSGustavo F. Padovan 	if (sdulen)
247603a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24770a708f8fSGustavo F. Padovan 
24780952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24790a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24800a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24810a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24820a708f8fSGustavo F. Padovan 	}
24830a708f8fSGustavo F. Padovan 
248418a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
24853ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
24860a708f8fSGustavo F. Padovan 	return skb;
24870a708f8fSGustavo F. Padovan }
24880a708f8fSGustavo F. Padovan 
248994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
249094122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
249194122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24920a708f8fSGustavo F. Padovan {
24930a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
249494122bbeSMat Martineau 	u16 sdu_len;
249594122bbeSMat Martineau 	size_t pdu_len;
249694122bbeSMat Martineau 	u8 sar;
24970a708f8fSGustavo F. Padovan 
2498b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24990a708f8fSGustavo F. Padovan 
250094122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
250194122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
250294122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
250394122bbeSMat Martineau 	 */
250494122bbeSMat Martineau 
250594122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
250694122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
250794122bbeSMat Martineau 
2508a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2509a549574dSMat Martineau 	if (!chan->hs_hcon)
251094122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
251194122bbeSMat Martineau 
251294122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
251335d401dfSGustavo Padovan 	if (chan->fcs)
251435d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
251535d401dfSGustavo Padovan 
2516ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
251794122bbeSMat Martineau 
251894122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
251994122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
252094122bbeSMat Martineau 
252194122bbeSMat Martineau 	if (len <= pdu_len) {
252294122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
252394122bbeSMat Martineau 		sdu_len = 0;
252494122bbeSMat Martineau 		pdu_len = len;
252594122bbeSMat Martineau 	} else {
252694122bbeSMat Martineau 		sar = L2CAP_SAR_START;
252794122bbeSMat Martineau 		sdu_len = len;
252894122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
252994122bbeSMat Martineau 	}
25300a708f8fSGustavo F. Padovan 
25310a708f8fSGustavo F. Padovan 	while (len > 0) {
253294122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25330a708f8fSGustavo F. Padovan 
25340a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
253594122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25360a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25370a708f8fSGustavo F. Padovan 		}
25380a708f8fSGustavo F. Padovan 
253994122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
254094122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25410a708f8fSGustavo F. Padovan 
254294122bbeSMat Martineau 		len -= pdu_len;
254394122bbeSMat Martineau 		if (sdu_len) {
254494122bbeSMat Martineau 			sdu_len = 0;
254594122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
254694122bbeSMat Martineau 		}
254794122bbeSMat Martineau 
254894122bbeSMat Martineau 		if (len <= pdu_len) {
254994122bbeSMat Martineau 			sar = L2CAP_SAR_END;
255094122bbeSMat Martineau 			pdu_len = len;
255194122bbeSMat Martineau 		} else {
255294122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
255394122bbeSMat Martineau 		}
255494122bbeSMat Martineau 	}
255594122bbeSMat Martineau 
2556f0f62799SGustavo Padovan 	return 0;
25570a708f8fSGustavo F. Padovan }
25580a708f8fSGustavo F. Padovan 
2559177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2560177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2561177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2562177f8f2bSJohan Hedberg {
2563177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2564177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2565177f8f2bSJohan Hedberg 	int err, count, hlen;
2566177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2567177f8f2bSJohan Hedberg 
2568177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2569177f8f2bSJohan Hedberg 
2570177f8f2bSJohan Hedberg 	if (!conn)
2571177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2572177f8f2bSJohan Hedberg 
2573177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2574177f8f2bSJohan Hedberg 
2575177f8f2bSJohan Hedberg 	if (sdulen)
2576177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2577177f8f2bSJohan Hedberg 
2578177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2579177f8f2bSJohan Hedberg 
2580177f8f2bSJohan Hedberg 	skb = chan->ops->alloc_skb(chan, count + hlen,
2581177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2582177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2583177f8f2bSJohan Hedberg 		return skb;
2584177f8f2bSJohan Hedberg 
2585177f8f2bSJohan Hedberg 	/* Create L2CAP header */
2586177f8f2bSJohan Hedberg 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2587177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2588177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2589177f8f2bSJohan Hedberg 
2590177f8f2bSJohan Hedberg 	if (sdulen)
2591177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2592177f8f2bSJohan Hedberg 
2593177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2594177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2595177f8f2bSJohan Hedberg 		kfree_skb(skb);
2596177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2597177f8f2bSJohan Hedberg 	}
2598177f8f2bSJohan Hedberg 
2599177f8f2bSJohan Hedberg 	return skb;
2600177f8f2bSJohan Hedberg }
2601177f8f2bSJohan Hedberg 
2602177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2603177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2604177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2605177f8f2bSJohan Hedberg {
2606177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2607177f8f2bSJohan Hedberg 	size_t pdu_len;
2608177f8f2bSJohan Hedberg 	u16 sdu_len;
2609177f8f2bSJohan Hedberg 
2610177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2611177f8f2bSJohan Hedberg 
2612177f8f2bSJohan Hedberg 	pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE;
2613177f8f2bSJohan Hedberg 
2614177f8f2bSJohan Hedberg 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2615177f8f2bSJohan Hedberg 
2616177f8f2bSJohan Hedberg 	sdu_len = len;
2617177f8f2bSJohan Hedberg 	pdu_len -= L2CAP_SDULEN_SIZE;
2618177f8f2bSJohan Hedberg 
2619177f8f2bSJohan Hedberg 	while (len > 0) {
2620177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2621177f8f2bSJohan Hedberg 			pdu_len = len;
2622177f8f2bSJohan Hedberg 
2623177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2624177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2625177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2626177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2627177f8f2bSJohan Hedberg 		}
2628177f8f2bSJohan Hedberg 
2629177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2630177f8f2bSJohan Hedberg 
2631177f8f2bSJohan Hedberg 		len -= pdu_len;
2632177f8f2bSJohan Hedberg 
2633177f8f2bSJohan Hedberg 		if (sdu_len) {
2634177f8f2bSJohan Hedberg 			sdu_len = 0;
2635177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2636177f8f2bSJohan Hedberg 		}
2637177f8f2bSJohan Hedberg 	}
2638177f8f2bSJohan Hedberg 
2639177f8f2bSJohan Hedberg 	return 0;
2640177f8f2bSJohan Hedberg }
2641177f8f2bSJohan Hedberg 
26425e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
26435e59b791SLuiz Augusto von Dentz 		    u32 priority)
26449a91a04aSGustavo F. Padovan {
26459a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26469a91a04aSGustavo F. Padovan 	int err;
264794122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26489a91a04aSGustavo F. Padovan 
264931e8ce80SSeung-Woo Kim 	if (!chan->conn)
265031e8ce80SSeung-Woo Kim 		return -ENOTCONN;
265131e8ce80SSeung-Woo Kim 
26529a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2653715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26545e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
26559a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26569a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26579a91a04aSGustavo F. Padovan 
26589a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26599a91a04aSGustavo F. Padovan 		return len;
26609a91a04aSGustavo F. Padovan 	}
26619a91a04aSGustavo F. Padovan 
26629a91a04aSGustavo F. Padovan 	switch (chan->mode) {
266338319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
2664177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2665177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2666177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2667177f8f2bSJohan Hedberg 
2668fad5fc89SJohan Hedberg 		if (!chan->tx_credits)
2669fad5fc89SJohan Hedberg 			return -EAGAIN;
2670fad5fc89SJohan Hedberg 
2671177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2672177f8f2bSJohan Hedberg 
2673177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2674177f8f2bSJohan Hedberg 
2675177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2676177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2677177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2678177f8f2bSJohan Hedberg 		}
2679177f8f2bSJohan Hedberg 
2680177f8f2bSJohan Hedberg 		if (err)
2681177f8f2bSJohan Hedberg 			return err;
2682177f8f2bSJohan Hedberg 
2683177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2684177f8f2bSJohan Hedberg 
2685177f8f2bSJohan Hedberg 		while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
2686177f8f2bSJohan Hedberg 			l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
2687177f8f2bSJohan Hedberg 			chan->tx_credits--;
2688177f8f2bSJohan Hedberg 		}
2689177f8f2bSJohan Hedberg 
2690177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2691177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2692177f8f2bSJohan Hedberg 
2693177f8f2bSJohan Hedberg 		err = len;
2694177f8f2bSJohan Hedberg 
2695177f8f2bSJohan Hedberg 		break;
2696177f8f2bSJohan Hedberg 
2697fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
26989a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
26999a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
27009a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
27019a91a04aSGustavo F. Padovan 
27029a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
27035e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
27049a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
27059a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
27069a91a04aSGustavo F. Padovan 
27079a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
27089a91a04aSGustavo F. Padovan 		err = len;
27099a91a04aSGustavo F. Padovan 		break;
27109a91a04aSGustavo F. Padovan 
27119a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27129a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
271394122bbeSMat Martineau 		/* Check outgoing MTU */
271494122bbeSMat Martineau 		if (len > chan->omtu) {
271594122bbeSMat Martineau 			err = -EMSGSIZE;
27169a91a04aSGustavo F. Padovan 			break;
27179a91a04aSGustavo F. Padovan 		}
27189a91a04aSGustavo F. Padovan 
271994122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
272094122bbeSMat Martineau 
272194122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
272294122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
272394122bbeSMat Martineau 		 * allocation.
272494122bbeSMat Martineau 		 */
272594122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
272694122bbeSMat Martineau 
272794122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
272894122bbeSMat Martineau 		 * check that it is still connected.
272994122bbeSMat Martineau 		 */
273094122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
273194122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
273294122bbeSMat Martineau 			err = -ENOTCONN;
27339a91a04aSGustavo F. Padovan 		}
27349a91a04aSGustavo F. Padovan 
273594122bbeSMat Martineau 		if (err)
273694122bbeSMat Martineau 			break;
273794122bbeSMat Martineau 
27383733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2739d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27403733937dSMat Martineau 		else
2741d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
274294122bbeSMat Martineau 
27439a91a04aSGustavo F. Padovan 		err = len;
27449a91a04aSGustavo F. Padovan 
274594122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
274694122bbeSMat Martineau 		 * seg_queue and need to be purged.
274794122bbeSMat Martineau 		 */
274894122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27499a91a04aSGustavo F. Padovan 		break;
27509a91a04aSGustavo F. Padovan 
27519a91a04aSGustavo F. Padovan 	default:
27529a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27539a91a04aSGustavo F. Padovan 		err = -EBADFD;
27549a91a04aSGustavo F. Padovan 	}
27559a91a04aSGustavo F. Padovan 
27569a91a04aSGustavo F. Padovan 	return err;
27579a91a04aSGustavo F. Padovan }
27589a91a04aSGustavo F. Padovan 
2759d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2760d2a7ac5dSMat Martineau {
2761bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2762bed68bdeSMat Martineau 	u16 seq;
2763bed68bdeSMat Martineau 
2764b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2765bed68bdeSMat Martineau 
2766bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2767bed68bdeSMat Martineau 	control.sframe = 1;
2768bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2769bed68bdeSMat Martineau 
2770bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2771bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2772bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2773bed68bdeSMat Martineau 			control.reqseq = seq;
2774bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2775bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2776bed68bdeSMat Martineau 		}
2777bed68bdeSMat Martineau 	}
2778bed68bdeSMat Martineau 
2779bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2780d2a7ac5dSMat Martineau }
2781d2a7ac5dSMat Martineau 
2782d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2783d2a7ac5dSMat Martineau {
2784bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2785bed68bdeSMat Martineau 
2786bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2787bed68bdeSMat Martineau 
2788bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2789bed68bdeSMat Martineau 		return;
2790bed68bdeSMat Martineau 
2791bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2792bed68bdeSMat Martineau 	control.sframe = 1;
2793bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2794bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2795bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2796d2a7ac5dSMat Martineau }
2797d2a7ac5dSMat Martineau 
2798d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2799d2a7ac5dSMat Martineau {
2800bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2801bed68bdeSMat Martineau 	u16 initial_head;
2802bed68bdeSMat Martineau 	u16 seq;
2803bed68bdeSMat Martineau 
2804b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2805bed68bdeSMat Martineau 
2806bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2807bed68bdeSMat Martineau 	control.sframe = 1;
2808bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2809bed68bdeSMat Martineau 
2810bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2811bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2812bed68bdeSMat Martineau 
2813bed68bdeSMat Martineau 	do {
2814bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2815bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2816bed68bdeSMat Martineau 			break;
2817bed68bdeSMat Martineau 
2818bed68bdeSMat Martineau 		control.reqseq = seq;
2819bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2820bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2821bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2822d2a7ac5dSMat Martineau }
2823d2a7ac5dSMat Martineau 
2824608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2825608bcc6dSMat Martineau {
2826608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2827608bcc6dSMat Martineau 	u16 ackseq;
2828608bcc6dSMat Martineau 
2829b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2830608bcc6dSMat Martineau 
2831608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2832608bcc6dSMat Martineau 		return;
2833608bcc6dSMat Martineau 
2834b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2835608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2836608bcc6dSMat Martineau 
2837608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2838608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2839608bcc6dSMat Martineau 
2840608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2841608bcc6dSMat Martineau 		if (acked_skb) {
2842608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2843608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2844608bcc6dSMat Martineau 			chan->unacked_frames--;
2845608bcc6dSMat Martineau 		}
2846608bcc6dSMat Martineau 	}
2847608bcc6dSMat Martineau 
2848608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2849608bcc6dSMat Martineau 
2850608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2851608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2852608bcc6dSMat Martineau 
2853b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2854608bcc6dSMat Martineau }
2855608bcc6dSMat Martineau 
2856608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2857608bcc6dSMat Martineau {
2858608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2859608bcc6dSMat Martineau 
2860608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2861608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2862608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2863608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2864608bcc6dSMat Martineau }
2865608bcc6dSMat Martineau 
2866d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2867608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2868608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2869608bcc6dSMat Martineau {
2870608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2871608bcc6dSMat Martineau 	       event);
2872608bcc6dSMat Martineau 
2873608bcc6dSMat Martineau 	switch (event) {
2874608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2875608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2876608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2877608bcc6dSMat Martineau 
2878608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2879608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2880608bcc6dSMat Martineau 		break;
2881608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2882608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2883608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2884608bcc6dSMat Martineau 
2885608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2886608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2887608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2888608bcc6dSMat Martineau 			 */
2889608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2890608bcc6dSMat Martineau 		}
2891608bcc6dSMat Martineau 
2892608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2893608bcc6dSMat Martineau 
2894608bcc6dSMat Martineau 		break;
2895608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2896608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2897608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2898608bcc6dSMat Martineau 
2899608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2900608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2901608bcc6dSMat Martineau 
2902608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2903608bcc6dSMat Martineau 			local_control.sframe = 1;
2904608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2905608bcc6dSMat Martineau 			local_control.poll = 1;
2906608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2907a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2908608bcc6dSMat Martineau 
2909608bcc6dSMat Martineau 			chan->retry_count = 1;
2910608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2911608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2912608bcc6dSMat Martineau 		}
2913608bcc6dSMat Martineau 		break;
2914608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2915608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2916608bcc6dSMat Martineau 		break;
2917608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2918608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2919608bcc6dSMat Martineau 		chan->retry_count = 1;
2920608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2921608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2922608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2923608bcc6dSMat Martineau 		break;
2924608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2925608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2926608bcc6dSMat Martineau 		chan->retry_count = 1;
2927608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2928608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2929608bcc6dSMat Martineau 		break;
2930608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2931608bcc6dSMat Martineau 		/* Nothing to process */
2932608bcc6dSMat Martineau 		break;
2933608bcc6dSMat Martineau 	default:
2934608bcc6dSMat Martineau 		break;
2935608bcc6dSMat Martineau 	}
2936608bcc6dSMat Martineau }
2937608bcc6dSMat Martineau 
2938d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2939608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2940608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2941608bcc6dSMat Martineau {
2942608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2943608bcc6dSMat Martineau 	       event);
2944608bcc6dSMat Martineau 
2945608bcc6dSMat Martineau 	switch (event) {
2946608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2947608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2948608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2949608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2950608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2951608bcc6dSMat Martineau 		break;
2952608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2953608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2954608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2955608bcc6dSMat Martineau 
2956608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2957608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2958608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2959608bcc6dSMat Martineau 			 */
2960608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2961608bcc6dSMat Martineau 		}
2962608bcc6dSMat Martineau 
2963608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2964608bcc6dSMat Martineau 
2965608bcc6dSMat Martineau 		break;
2966608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2967608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2968608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2969608bcc6dSMat Martineau 
2970608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2971608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2972608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2973608bcc6dSMat Martineau 			local_control.sframe = 1;
2974608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2975608bcc6dSMat Martineau 			local_control.poll = 1;
2976608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2977a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2978608bcc6dSMat Martineau 
2979608bcc6dSMat Martineau 			chan->retry_count = 1;
2980608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2981608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2982608bcc6dSMat Martineau 		}
2983608bcc6dSMat Martineau 		break;
2984608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2985608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2986608bcc6dSMat Martineau 
2987608bcc6dSMat Martineau 		/* Fall through */
2988608bcc6dSMat Martineau 
2989608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2990608bcc6dSMat Martineau 		if (control && control->final) {
2991608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2992608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2993608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2994608bcc6dSMat Martineau 			chan->retry_count = 0;
2995608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2996608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2997608bcc6dSMat Martineau 		}
2998608bcc6dSMat Martineau 		break;
2999608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
3000608bcc6dSMat Martineau 		/* Ignore */
3001608bcc6dSMat Martineau 		break;
3002608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
3003608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
3004608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
3005608bcc6dSMat Martineau 			__set_monitor_timer(chan);
3006608bcc6dSMat Martineau 			chan->retry_count++;
3007608bcc6dSMat Martineau 		} else {
30085e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
3009608bcc6dSMat Martineau 		}
3010608bcc6dSMat Martineau 		break;
3011608bcc6dSMat Martineau 	default:
3012608bcc6dSMat Martineau 		break;
3013608bcc6dSMat Martineau 	}
3014608bcc6dSMat Martineau }
3015608bcc6dSMat Martineau 
3016d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
3017608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
3018608bcc6dSMat Martineau {
3019608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
3020608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
3021608bcc6dSMat Martineau 
3022608bcc6dSMat Martineau 	switch (chan->tx_state) {
3023608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3024d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3025608bcc6dSMat Martineau 		break;
3026608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3027d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3028608bcc6dSMat Martineau 		break;
3029608bcc6dSMat Martineau 	default:
3030608bcc6dSMat Martineau 		/* Ignore event */
3031608bcc6dSMat Martineau 		break;
3032608bcc6dSMat Martineau 	}
3033608bcc6dSMat Martineau }
3034608bcc6dSMat Martineau 
30354b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30364b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30374b51dae9SMat Martineau {
30384b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3039401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30404b51dae9SMat Martineau }
30414b51dae9SMat Martineau 
3042f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3043f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3044f80842a8SMat Martineau {
3045f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3046401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3047f80842a8SMat Martineau }
3048f80842a8SMat Martineau 
30490a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30500a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30510a708f8fSGustavo F. Padovan {
30520a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
305348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30540a708f8fSGustavo F. Padovan 
30550a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30560a708f8fSGustavo F. Padovan 
30573df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30583d57dc68SGustavo F. Padovan 
30593df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3060715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30610a708f8fSGustavo F. Padovan 			continue;
30620a708f8fSGustavo F. Padovan 
30637f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
30647f5396a7SGustavo Padovan 		if (bt_cb(skb)->chan == chan)
30650a708f8fSGustavo F. Padovan 			continue;
30667f5396a7SGustavo Padovan 
30678bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30680a708f8fSGustavo F. Padovan 		if (!nskb)
30690a708f8fSGustavo F. Padovan 			continue;
307080b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30710a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30720a708f8fSGustavo F. Padovan 	}
30733d57dc68SGustavo F. Padovan 
30743df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30750a708f8fSGustavo F. Padovan }
30760a708f8fSGustavo F. Padovan 
30770a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3078b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3079b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30800a708f8fSGustavo F. Padovan {
30810a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30820a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30830a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30840a708f8fSGustavo F. Padovan 	int len, count;
30850a708f8fSGustavo F. Padovan 
3086b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30870a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
30880a708f8fSGustavo F. Padovan 
3089300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3090300b962eSAnderson Lizardo 		return NULL;
3091300b962eSAnderson Lizardo 
30920a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
30930a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
30940a708f8fSGustavo F. Padovan 
30958bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
30960a708f8fSGustavo F. Padovan 	if (!skb)
30970a708f8fSGustavo F. Padovan 		return NULL;
30980a708f8fSGustavo F. Padovan 
30990a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
31000a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
31013300d9a9SClaudio Takahasi 
31023300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3103ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
31043300d9a9SClaudio Takahasi 	else
3105ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
31060a708f8fSGustavo F. Padovan 
31070a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
31080a708f8fSGustavo F. Padovan 	cmd->code  = code;
31090a708f8fSGustavo F. Padovan 	cmd->ident = ident;
31100a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
31110a708f8fSGustavo F. Padovan 
31120a708f8fSGustavo F. Padovan 	if (dlen) {
31130a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
31140a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
31150a708f8fSGustavo F. Padovan 		data += count;
31160a708f8fSGustavo F. Padovan 	}
31170a708f8fSGustavo F. Padovan 
31180a708f8fSGustavo F. Padovan 	len -= skb->len;
31190a708f8fSGustavo F. Padovan 
31200a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
31210a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31220a708f8fSGustavo F. Padovan 	while (len) {
31230a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31240a708f8fSGustavo F. Padovan 
31258bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31260a708f8fSGustavo F. Padovan 		if (!*frag)
31270a708f8fSGustavo F. Padovan 			goto fail;
31280a708f8fSGustavo F. Padovan 
31290a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
31300a708f8fSGustavo F. Padovan 
31310a708f8fSGustavo F. Padovan 		len  -= count;
31320a708f8fSGustavo F. Padovan 		data += count;
31330a708f8fSGustavo F. Padovan 
31340a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31350a708f8fSGustavo F. Padovan 	}
31360a708f8fSGustavo F. Padovan 
31370a708f8fSGustavo F. Padovan 	return skb;
31380a708f8fSGustavo F. Padovan 
31390a708f8fSGustavo F. Padovan fail:
31400a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31410a708f8fSGustavo F. Padovan 	return NULL;
31420a708f8fSGustavo F. Padovan }
31430a708f8fSGustavo F. Padovan 
31442d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31452d792818SGustavo Padovan 				     unsigned long *val)
31460a708f8fSGustavo F. Padovan {
31470a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31480a708f8fSGustavo F. Padovan 	int len;
31490a708f8fSGustavo F. Padovan 
31500a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31510a708f8fSGustavo F. Padovan 	*ptr += len;
31520a708f8fSGustavo F. Padovan 
31530a708f8fSGustavo F. Padovan 	*type = opt->type;
31540a708f8fSGustavo F. Padovan 	*olen = opt->len;
31550a708f8fSGustavo F. Padovan 
31560a708f8fSGustavo F. Padovan 	switch (opt->len) {
31570a708f8fSGustavo F. Padovan 	case 1:
31580a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31590a708f8fSGustavo F. Padovan 		break;
31600a708f8fSGustavo F. Padovan 
31610a708f8fSGustavo F. Padovan 	case 2:
31620a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31630a708f8fSGustavo F. Padovan 		break;
31640a708f8fSGustavo F. Padovan 
31650a708f8fSGustavo F. Padovan 	case 4:
31660a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31670a708f8fSGustavo F. Padovan 		break;
31680a708f8fSGustavo F. Padovan 
31690a708f8fSGustavo F. Padovan 	default:
31700a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31710a708f8fSGustavo F. Padovan 		break;
31720a708f8fSGustavo F. Padovan 	}
31730a708f8fSGustavo F. Padovan 
3174b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31750a708f8fSGustavo F. Padovan 	return len;
31760a708f8fSGustavo F. Padovan }
31770a708f8fSGustavo F. Padovan 
31780a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
31790a708f8fSGustavo F. Padovan {
31800a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31810a708f8fSGustavo F. Padovan 
3182b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31830a708f8fSGustavo F. Padovan 
31840a708f8fSGustavo F. Padovan 	opt->type = type;
31850a708f8fSGustavo F. Padovan 	opt->len  = len;
31860a708f8fSGustavo F. Padovan 
31870a708f8fSGustavo F. Padovan 	switch (len) {
31880a708f8fSGustavo F. Padovan 	case 1:
31890a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
31900a708f8fSGustavo F. Padovan 		break;
31910a708f8fSGustavo F. Padovan 
31920a708f8fSGustavo F. Padovan 	case 2:
31930a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
31940a708f8fSGustavo F. Padovan 		break;
31950a708f8fSGustavo F. Padovan 
31960a708f8fSGustavo F. Padovan 	case 4:
31970a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
31980a708f8fSGustavo F. Padovan 		break;
31990a708f8fSGustavo F. Padovan 
32000a708f8fSGustavo F. Padovan 	default:
32010a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
32020a708f8fSGustavo F. Padovan 		break;
32030a708f8fSGustavo F. Padovan 	}
32040a708f8fSGustavo F. Padovan 
32050a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
32060a708f8fSGustavo F. Padovan }
32070a708f8fSGustavo F. Padovan 
3208f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
3209f89cef09SAndrei Emeltchenko {
3210f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3211f89cef09SAndrei Emeltchenko 
3212f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3213f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3214f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3215f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3216f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3217f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3218ac73498cSAndrei Emeltchenko 		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
32198936fa6dSAndrei Emeltchenko 		efs.flush_to	= __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3220f89cef09SAndrei Emeltchenko 		break;
3221f89cef09SAndrei Emeltchenko 
3222f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3223f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3224f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3225f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3226f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3227f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3228f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3229f89cef09SAndrei Emeltchenko 		break;
3230f89cef09SAndrei Emeltchenko 
3231f89cef09SAndrei Emeltchenko 	default:
3232f89cef09SAndrei Emeltchenko 		return;
3233f89cef09SAndrei Emeltchenko 	}
3234f89cef09SAndrei Emeltchenko 
3235f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3236f89cef09SAndrei Emeltchenko 			   (unsigned long) &efs);
3237f89cef09SAndrei Emeltchenko }
3238f89cef09SAndrei Emeltchenko 
3239721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32400a708f8fSGustavo F. Padovan {
3241721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3242721c4181SGustavo F. Padovan 					       ack_timer.work);
32430362520bSMat Martineau 	u16 frames_to_ack;
32440a708f8fSGustavo F. Padovan 
32452fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32462fb9b3d4SGustavo F. Padovan 
32476be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32486be36555SAndrei Emeltchenko 
32490362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32500362520bSMat Martineau 				     chan->last_acked_seq);
32510362520bSMat Martineau 
32520362520bSMat Martineau 	if (frames_to_ack)
32530362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32546be36555SAndrei Emeltchenko 
32556be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
325609bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32570a708f8fSGustavo F. Padovan }
32580a708f8fSGustavo F. Padovan 
3259466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32600a708f8fSGustavo F. Padovan {
32613c588192SMat Martineau 	int err;
32623c588192SMat Martineau 
3263105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3264105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
326542e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32666a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
326742e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32686a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3269105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3270105bdf9eSMat Martineau 	chan->sdu = NULL;
3271105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3272105bdf9eSMat Martineau 	chan->sdu_len = 0;
3273105bdf9eSMat Martineau 
3274d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3275d34c34fbSMat Martineau 
32766ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32776ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
327808333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
327908333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
328008333283SMat Martineau 
3281105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3282105bdf9eSMat Martineau 		return 0;
3283105bdf9eSMat Martineau 
3284105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3285105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
32860a708f8fSGustavo F. Padovan 
3287721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3288721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3289721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
32900a708f8fSGustavo F. Padovan 
3291f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
32920a708f8fSGustavo F. Padovan 
32933c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
32943c588192SMat Martineau 	if (err < 0)
32953c588192SMat Martineau 		return err;
32963c588192SMat Martineau 
32979dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
32989dc9affcSMat Martineau 	if (err < 0)
32999dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
33009dc9affcSMat Martineau 
33019dc9affcSMat Martineau 	return err;
33020a708f8fSGustavo F. Padovan }
33030a708f8fSGustavo F. Padovan 
33040a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
33050a708f8fSGustavo F. Padovan {
33060a708f8fSGustavo F. Padovan 	switch (mode) {
33070a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33080a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33090a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
33100a708f8fSGustavo F. Padovan 			return mode;
33110a708f8fSGustavo F. Padovan 		/* fall through */
33120a708f8fSGustavo F. Padovan 	default:
33130a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
33140a708f8fSGustavo F. Padovan 	}
33150a708f8fSGustavo F. Padovan }
33160a708f8fSGustavo F. Padovan 
3317848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
33186327eb98SAndrei Emeltchenko {
3319848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
33206327eb98SAndrei Emeltchenko }
33216327eb98SAndrei Emeltchenko 
3322848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3323f89cef09SAndrei Emeltchenko {
3324848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
3325f89cef09SAndrei Emeltchenko }
3326f89cef09SAndrei Emeltchenko 
332736c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
332836c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
332936c86c85SMat Martineau {
33306ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
333136c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
333236c86c85SMat Martineau 
333336c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
333436c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
333536c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
333636c86c85SMat Martineau 		 * controllers is 10 seconds.
333736c86c85SMat Martineau 		 *
333836c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
333936c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
334036c86c85SMat Martineau 		 * will result in a timeout that meets the above
334136c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
334236c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
334336c86c85SMat Martineau 		 */
334436c86c85SMat Martineau 
334536c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
334636c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
334736c86c85SMat Martineau 
334836c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
334936c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
335036c86c85SMat Martineau 		 * controller.
335136c86c85SMat Martineau 		 */
335236c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
335336c86c85SMat Martineau 
335436c86c85SMat Martineau 		if (ertm_to > 0xffff)
335536c86c85SMat Martineau 			ertm_to = 0xffff;
335636c86c85SMat Martineau 
335736c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
335836c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
335936c86c85SMat Martineau 	} else {
336036c86c85SMat Martineau 		rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
336136c86c85SMat Martineau 		rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
336236c86c85SMat Martineau 	}
336336c86c85SMat Martineau }
336436c86c85SMat Martineau 
33656327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33666327eb98SAndrei Emeltchenko {
33676327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3368848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33696327eb98SAndrei Emeltchenko 		/* use extended control field */
33706327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3371836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3372836be934SAndrei Emeltchenko 	} else {
33736327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33746327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3375836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3376836be934SAndrei Emeltchenko 	}
3377c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33786327eb98SAndrei Emeltchenko }
33796327eb98SAndrei Emeltchenko 
3380710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
33810a708f8fSGustavo F. Padovan {
33820a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
33830c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
33840a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3385c8f79162SAndrei Emeltchenko 	u16 size;
33860a708f8fSGustavo F. Padovan 
338749208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
33880a708f8fSGustavo F. Padovan 
338973ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
33900a708f8fSGustavo F. Padovan 		goto done;
33910a708f8fSGustavo F. Padovan 
33920c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
33930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33940a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3395c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
33960a708f8fSGustavo F. Padovan 			break;
33970a708f8fSGustavo F. Padovan 
3398848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3399f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3400f89cef09SAndrei Emeltchenko 
34010a708f8fSGustavo F. Padovan 		/* fall through */
34020a708f8fSGustavo F. Padovan 	default:
34038c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
34040a708f8fSGustavo F. Padovan 		break;
34050a708f8fSGustavo F. Padovan 	}
34060a708f8fSGustavo F. Padovan 
34070a708f8fSGustavo F. Padovan done:
34080c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
34090c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
34100a708f8fSGustavo F. Padovan 
34110c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34120a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
34138c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
34148c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
34150a708f8fSGustavo F. Padovan 			break;
34160a708f8fSGustavo F. Padovan 
34170a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
34180a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34190a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34200a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34210a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34220a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34230a708f8fSGustavo F. Padovan 
34240a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34250a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34260a708f8fSGustavo F. Padovan 		break;
34270a708f8fSGustavo F. Padovan 
34280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34290a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
343047d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
343136c86c85SMat Martineau 
343236c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3433c8f79162SAndrei Emeltchenko 
3434c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34352d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3436c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3437c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34380a708f8fSGustavo F. Padovan 
34396327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
34406327eb98SAndrei Emeltchenko 
34416327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
34426327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
34430a708f8fSGustavo F. Padovan 
34440a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34450a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34460a708f8fSGustavo F. Padovan 
3447f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3448f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3449f89cef09SAndrei Emeltchenko 
34506327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
34516327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
34526327eb98SAndrei Emeltchenko 					   chan->tx_win);
345360918918SAndrei Emeltchenko 
345460918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
345560918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3456f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
345760918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
345860918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
345960918918SAndrei Emeltchenko 						   chan->fcs);
346060918918SAndrei Emeltchenko 			}
34610a708f8fSGustavo F. Padovan 		break;
34620a708f8fSGustavo F. Padovan 
34630a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3464273759e2SMat Martineau 		l2cap_txwin_setup(chan);
34650a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
34660a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34670a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34680a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34690a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3470c8f79162SAndrei Emeltchenko 
3471c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34722d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3473c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3474c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34750a708f8fSGustavo F. Padovan 
34760a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34770a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34780a708f8fSGustavo F. Padovan 
3479f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3480f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3481f89cef09SAndrei Emeltchenko 
348260918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
348347d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3484f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
348547d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
348660918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
348760918918SAndrei Emeltchenko 						   chan->fcs);
34880a708f8fSGustavo F. Padovan 			}
34890a708f8fSGustavo F. Padovan 		break;
34900a708f8fSGustavo F. Padovan 	}
34910a708f8fSGustavo F. Padovan 
3492fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
349359e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
34940a708f8fSGustavo F. Padovan 
34950a708f8fSGustavo F. Padovan 	return ptr - data;
34960a708f8fSGustavo F. Padovan }
34970a708f8fSGustavo F. Padovan 
349873ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34990a708f8fSGustavo F. Padovan {
35000a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
35010a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
350273ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
350373ffa904SGustavo F. Padovan 	int len = chan->conf_len;
35040a708f8fSGustavo F. Padovan 	int type, hint, olen;
35050a708f8fSGustavo F. Padovan 	unsigned long val;
35060a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
350742dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
350842dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
35090a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
35100a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3511c8f79162SAndrei Emeltchenko 	u16 size;
35120a708f8fSGustavo F. Padovan 
351373ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
35140a708f8fSGustavo F. Padovan 
35150a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35160a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
35170a708f8fSGustavo F. Padovan 
35180a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
35190a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
35200a708f8fSGustavo F. Padovan 
35210a708f8fSGustavo F. Padovan 		switch (type) {
35220a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
35230a708f8fSGustavo F. Padovan 			mtu = val;
35240a708f8fSGustavo F. Padovan 			break;
35250a708f8fSGustavo F. Padovan 
35260a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
35270c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35280a708f8fSGustavo F. Padovan 			break;
35290a708f8fSGustavo F. Padovan 
35300a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
35310a708f8fSGustavo F. Padovan 			break;
35320a708f8fSGustavo F. Padovan 
35330a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
35340a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
35350a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
35360a708f8fSGustavo F. Padovan 			break;
35370a708f8fSGustavo F. Padovan 
35380a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
35390a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3540f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
354142dceae2SAndrei Emeltchenko 			break;
35420a708f8fSGustavo F. Padovan 
354342dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
354442dceae2SAndrei Emeltchenko 			remote_efs = 1;
354542dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
354642dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
35470a708f8fSGustavo F. Padovan 			break;
35480a708f8fSGustavo F. Padovan 
35496327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3550848566b3SMarcel Holtmann 			if (!chan->conn->hs_enabled)
35516327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
35526327eb98SAndrei Emeltchenko 
35536327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
35546327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3555836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
35566327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
35570a708f8fSGustavo F. Padovan 			break;
35580a708f8fSGustavo F. Padovan 
35590a708f8fSGustavo F. Padovan 		default:
35600a708f8fSGustavo F. Padovan 			if (hint)
35610a708f8fSGustavo F. Padovan 				break;
35620a708f8fSGustavo F. Padovan 
35630a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
35640a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
35650a708f8fSGustavo F. Padovan 			break;
35660a708f8fSGustavo F. Padovan 		}
35670a708f8fSGustavo F. Padovan 	}
35680a708f8fSGustavo F. Padovan 
356973ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
35700a708f8fSGustavo F. Padovan 		goto done;
35710a708f8fSGustavo F. Padovan 
35720c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
35730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
35740a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3575c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
35760c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
35778c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
35780a708f8fSGustavo F. Padovan 			break;
35790a708f8fSGustavo F. Padovan 		}
35800a708f8fSGustavo F. Padovan 
358142dceae2SAndrei Emeltchenko 		if (remote_efs) {
3582848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
358342dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
358442dceae2SAndrei Emeltchenko 			else
358542dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
358642dceae2SAndrei Emeltchenko 		}
358742dceae2SAndrei Emeltchenko 
35880c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
35890a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
35900a708f8fSGustavo F. Padovan 
35910a708f8fSGustavo F. Padovan 		break;
35920a708f8fSGustavo F. Padovan 	}
35930a708f8fSGustavo F. Padovan 
35940a708f8fSGustavo F. Padovan done:
35950c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
35960a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
35970c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
35980a708f8fSGustavo F. Padovan 
359973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
36000a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36010a708f8fSGustavo F. Padovan 
36022d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
36032d792818SGustavo Padovan 				   (unsigned long) &rfc);
36040a708f8fSGustavo F. Padovan 	}
36050a708f8fSGustavo F. Padovan 
36060a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
36070a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
36080a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
36090a708f8fSGustavo F. Padovan 
36100a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
36110a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36120a708f8fSGustavo F. Padovan 		else {
36130c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3614c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
36150a708f8fSGustavo F. Padovan 		}
36160c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
36170a708f8fSGustavo F. Padovan 
361842dceae2SAndrei Emeltchenko 		if (remote_efs) {
361942dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
362042dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
362142dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
362242dceae2SAndrei Emeltchenko 
362342dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
362442dceae2SAndrei Emeltchenko 
362542dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
362642dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
362742dceae2SAndrei Emeltchenko 
362842dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
362942dceae2SAndrei Emeltchenko 						   sizeof(efs),
363042dceae2SAndrei Emeltchenko 						   (unsigned long) &efs);
36310e8b207eSAndrei Emeltchenko 			} else {
36323e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
36330e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
36340e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
363542dceae2SAndrei Emeltchenko 			}
363642dceae2SAndrei Emeltchenko 		}
363742dceae2SAndrei Emeltchenko 
36380a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36390a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
364047d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3641c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36420a708f8fSGustavo F. Padovan 			break;
36430a708f8fSGustavo F. Padovan 
36440a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
36456327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
36462c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
36476327eb98SAndrei Emeltchenko 			else
36486327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
36496327eb98SAndrei Emeltchenko 
36502c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
36510a708f8fSGustavo F. Padovan 
3652c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36532d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36542d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3655c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3656c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36570a708f8fSGustavo F. Padovan 
365836c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
36590a708f8fSGustavo F. Padovan 
3660c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36610a708f8fSGustavo F. Padovan 
36620a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
36630a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
36640a708f8fSGustavo F. Padovan 
366542dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
366642dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
366742dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
366842dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
366942dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
367042dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
367142dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
367242dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
367342dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
367442dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
367542dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
36762d792818SGustavo Padovan 						   sizeof(efs),
36772d792818SGustavo Padovan 						   (unsigned long) &efs);
367842dceae2SAndrei Emeltchenko 			}
36790a708f8fSGustavo F. Padovan 			break;
36800a708f8fSGustavo F. Padovan 
36810a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3682c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36832d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36842d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3685c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3686c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36870a708f8fSGustavo F. Padovan 
3688c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36890a708f8fSGustavo F. Padovan 
36902d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
36912d792818SGustavo Padovan 					   (unsigned long) &rfc);
36920a708f8fSGustavo F. Padovan 
36930a708f8fSGustavo F. Padovan 			break;
36940a708f8fSGustavo F. Padovan 
36950a708f8fSGustavo F. Padovan 		default:
36960a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36970a708f8fSGustavo F. Padovan 
36980a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
36990c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
37000a708f8fSGustavo F. Padovan 		}
37010a708f8fSGustavo F. Padovan 
37020a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3703c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37040a708f8fSGustavo F. Padovan 	}
3705fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37060a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
370759e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
37080a708f8fSGustavo F. Padovan 
37090a708f8fSGustavo F. Padovan 	return ptr - data;
37100a708f8fSGustavo F. Padovan }
37110a708f8fSGustavo F. Padovan 
37122d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
37132d792818SGustavo Padovan 				void *data, u16 *result)
37140a708f8fSGustavo F. Padovan {
37150a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
37160a708f8fSGustavo F. Padovan 	void *ptr = req->data;
37170a708f8fSGustavo F. Padovan 	int type, olen;
37180a708f8fSGustavo F. Padovan 	unsigned long val;
371936e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
372066af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
37210a708f8fSGustavo F. Padovan 
3722fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
37230a708f8fSGustavo F. Padovan 
37240a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37250a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37260a708f8fSGustavo F. Padovan 
37270a708f8fSGustavo F. Padovan 		switch (type) {
37280a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
37290a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
37300a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
37310c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
37320a708f8fSGustavo F. Padovan 			} else
37330c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
37340c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
37350a708f8fSGustavo F. Padovan 			break;
37360a708f8fSGustavo F. Padovan 
37370a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
37380c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
37390a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
37400c1bc5c6SGustavo F. Padovan 					   2, chan->flush_to);
37410a708f8fSGustavo F. Padovan 			break;
37420a708f8fSGustavo F. Padovan 
37430a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
37440a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
37450a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
37460a708f8fSGustavo F. Padovan 
3747c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
37480c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
37490a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
37500a708f8fSGustavo F. Padovan 
375147d1ec61SGustavo F. Padovan 			chan->fcs = 0;
37520a708f8fSGustavo F. Padovan 
37530a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
37540a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
37550a708f8fSGustavo F. Padovan 			break;
37566327eb98SAndrei Emeltchenko 
37576327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3758c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
37593e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
37603e6b3b95SGustavo F. Padovan 					   chan->tx_win);
37616327eb98SAndrei Emeltchenko 			break;
376266af7aafSAndrei Emeltchenko 
376366af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
376466af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
376566af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
376666af7aafSAndrei Emeltchenko 
376766af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
376866af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
376966af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
377066af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
377166af7aafSAndrei Emeltchenko 
37722d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
37732d792818SGustavo Padovan 					   (unsigned long) &efs);
377466af7aafSAndrei Emeltchenko 			break;
3775cbabee78SAndrei Emeltchenko 
3776cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3777cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3778cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3779f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3780cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3781cbabee78SAndrei Emeltchenko 			break;
37820a708f8fSGustavo F. Padovan 		}
37830a708f8fSGustavo F. Padovan 	}
37840a708f8fSGustavo F. Padovan 
37850c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
37860a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
37870a708f8fSGustavo F. Padovan 
37880c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
37890a708f8fSGustavo F. Padovan 
37900e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
37910a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37920a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
379347d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
379447d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
379547d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3796c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3797c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3798c20f8e35SMat Martineau 						      rfc.txwin_size);
379966af7aafSAndrei Emeltchenko 
380066af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
380166af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
380266af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
380366af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
380466af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
380566af7aafSAndrei Emeltchenko 				chan->local_flush_to =
380666af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
380766af7aafSAndrei Emeltchenko 			}
38080a708f8fSGustavo F. Padovan 			break;
380966af7aafSAndrei Emeltchenko 
38100a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
381147d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38120a708f8fSGustavo F. Padovan 		}
38130a708f8fSGustavo F. Padovan 	}
38140a708f8fSGustavo F. Padovan 
3815fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
381659e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
38170a708f8fSGustavo F. Padovan 
38180a708f8fSGustavo F. Padovan 	return ptr - data;
38190a708f8fSGustavo F. Padovan }
38200a708f8fSGustavo F. Padovan 
38212d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
38222d792818SGustavo Padovan 				u16 result, u16 flags)
38230a708f8fSGustavo F. Padovan {
38240a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
38250a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
38260a708f8fSGustavo F. Padovan 
3827fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
38280a708f8fSGustavo F. Padovan 
3829fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
38300a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
38310a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
38320a708f8fSGustavo F. Padovan 
38330a708f8fSGustavo F. Padovan 	return ptr - data;
38340a708f8fSGustavo F. Padovan }
38350a708f8fSGustavo F. Padovan 
383627e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
383727e2d4c8SJohan Hedberg {
383827e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
383927e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
384027e2d4c8SJohan Hedberg 
384127e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
384227e2d4c8SJohan Hedberg 
384327e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
384427e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
38453916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
38460cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
384727e2d4c8SJohan Hedberg 	rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
384827e2d4c8SJohan Hedberg 
384927e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
385027e2d4c8SJohan Hedberg 		       &rsp);
385127e2d4c8SJohan Hedberg }
385227e2d4c8SJohan Hedberg 
38538c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3854710f9b0aSGustavo F. Padovan {
3855710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
38568c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3857710f9b0aSGustavo F. Padovan 	u8 buf[128];
3858439f34acSAndrei Emeltchenko 	u8 rsp_code;
3859710f9b0aSGustavo F. Padovan 
3860fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3861fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3862ac73498cSAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3863ac73498cSAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3864439f34acSAndrei Emeltchenko 
3865439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3866439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3867439f34acSAndrei Emeltchenko 	else
3868439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3869439f34acSAndrei Emeltchenko 
3870439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3871439f34acSAndrei Emeltchenko 
3872439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3873710f9b0aSGustavo F. Padovan 
3874c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3875710f9b0aSGustavo F. Padovan 		return;
3876710f9b0aSGustavo F. Padovan 
3877710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3878710f9b0aSGustavo F. Padovan 		       l2cap_build_conf_req(chan, buf), buf);
3879710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3880710f9b0aSGustavo F. Padovan }
3881710f9b0aSGustavo F. Padovan 
388247d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
38830a708f8fSGustavo F. Padovan {
38840a708f8fSGustavo F. Padovan 	int type, olen;
38850a708f8fSGustavo F. Padovan 	unsigned long val;
3886c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3887c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3888c20f8e35SMat Martineau 	 */
3889c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3890c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3891c20f8e35SMat Martineau 		.mode = chan->mode,
3892c20f8e35SMat Martineau 		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3893c20f8e35SMat Martineau 		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3894c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3895c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3896c20f8e35SMat Martineau 	};
38970a708f8fSGustavo F. Padovan 
389847d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
38990a708f8fSGustavo F. Padovan 
39000c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
39010a708f8fSGustavo F. Padovan 		return;
39020a708f8fSGustavo F. Padovan 
39030a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
39040a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
39050a708f8fSGustavo F. Padovan 
3906c20f8e35SMat Martineau 		switch (type) {
3907c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3908c20f8e35SMat Martineau 			if (olen == sizeof(rfc))
39090a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
3910c20f8e35SMat Martineau 			break;
3911c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3912c20f8e35SMat Martineau 			txwin_ext = val;
3913c20f8e35SMat Martineau 			break;
3914c20f8e35SMat Martineau 		}
39150a708f8fSGustavo F. Padovan 	}
39160a708f8fSGustavo F. Padovan 
39170a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
39180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
391947d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
392047d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
392147d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3922c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3923c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3924c20f8e35SMat Martineau 		else
3925c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3926c20f8e35SMat Martineau 					      rfc.txwin_size);
39270a708f8fSGustavo F. Padovan 		break;
39280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
392947d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
39300a708f8fSGustavo F. Padovan 	}
39310a708f8fSGustavo F. Padovan }
39320a708f8fSGustavo F. Padovan 
39332d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3934cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3935cb3b3152SJohan Hedberg 				    u8 *data)
39360a708f8fSGustavo F. Padovan {
3937e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
39380a708f8fSGustavo F. Padovan 
3939cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3940cb3b3152SJohan Hedberg 		return -EPROTO;
3941cb3b3152SJohan Hedberg 
3942e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
39430a708f8fSGustavo F. Padovan 		return 0;
39440a708f8fSGustavo F. Padovan 
39450a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
39460a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
394717cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
39480a708f8fSGustavo F. Padovan 
39490a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39500a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39510a708f8fSGustavo F. Padovan 
39520a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39530a708f8fSGustavo F. Padovan 	}
39540a708f8fSGustavo F. Padovan 
39550a708f8fSGustavo F. Padovan 	return 0;
39560a708f8fSGustavo F. Padovan }
39570a708f8fSGustavo F. Padovan 
39581700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
39591700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
39604c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
39610a708f8fSGustavo F. Padovan {
39620a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39630a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
396423691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
39650a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
39660a708f8fSGustavo F. Padovan 
39670a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
39680a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
39690a708f8fSGustavo F. Padovan 
3970097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
39710a708f8fSGustavo F. Padovan 
39720a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
39736f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3974bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
397523691d75SGustavo F. Padovan 	if (!pchan) {
39760a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
39770a708f8fSGustavo F. Padovan 		goto sendresp;
39780a708f8fSGustavo F. Padovan 	}
39790a708f8fSGustavo F. Padovan 
39803df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
39818ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
39820a708f8fSGustavo F. Padovan 
39830a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
39842983fd68SAndrei Emeltchenko 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
39850a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
39869f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39870a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
39880a708f8fSGustavo F. Padovan 		goto response;
39890a708f8fSGustavo F. Padovan 	}
39900a708f8fSGustavo F. Padovan 
39910a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
39920a708f8fSGustavo F. Padovan 
39932dfa1003SGustavo Padovan 	/* Check if we already have channel with that dcid */
39942dfa1003SGustavo Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid))
39952dfa1003SGustavo Padovan 		goto response;
39962dfa1003SGustavo Padovan 
399780b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
399880808e43SGustavo F. Padovan 	if (!chan)
39990a708f8fSGustavo F. Padovan 		goto response;
40000a708f8fSGustavo F. Padovan 
4001330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
4002330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
4003330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
4004330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
4005330b6c15SSyam Sidhardhan 	 */
4006330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
4007330b6c15SSyam Sidhardhan 
40087eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
40097eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
40104f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
40114f1654e0SMarcel Holtmann 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
4012fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
4013fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
40141700915fSMat Martineau 	chan->local_amp_id = amp_id;
40150a708f8fSGustavo F. Padovan 
40166be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
401748454079SGustavo F. Padovan 
4018fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
40190a708f8fSGustavo F. Padovan 
40208d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
40210a708f8fSGustavo F. Padovan 
4022fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
40230a708f8fSGustavo F. Padovan 
40240a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4025d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
4026bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4027f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
40280a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
40290a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
40302dc4e510SGustavo Padovan 				chan->ops->defer(chan);
40310a708f8fSGustavo F. Padovan 			} else {
40321700915fSMat Martineau 				/* Force pending result for AMP controllers.
40331700915fSMat Martineau 				 * The connection will succeed after the
40341700915fSMat Martineau 				 * physical link is up.
40351700915fSMat Martineau 				 */
40366ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4037f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
40380a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
40396ed971caSMarcel Holtmann 				} else {
4040f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
40416ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
40421700915fSMat Martineau 				}
40430a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
40440a708f8fSGustavo F. Padovan 			}
40450a708f8fSGustavo F. Padovan 		} else {
4046f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
40470a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
40480a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
40490a708f8fSGustavo F. Padovan 		}
40500a708f8fSGustavo F. Padovan 	} else {
4051f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
40520a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
40530a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
40540a708f8fSGustavo F. Padovan 	}
40550a708f8fSGustavo F. Padovan 
40560a708f8fSGustavo F. Padovan response:
40578ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
40583df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40590a708f8fSGustavo F. Padovan 
40600a708f8fSGustavo F. Padovan sendresp:
40610a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
40620a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
40630a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
40640a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
40654c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40660a708f8fSGustavo F. Padovan 
40670a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40680a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4069ac73498cSAndrei Emeltchenko 		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
40700a708f8fSGustavo F. Padovan 
40710a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40720a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
40730a708f8fSGustavo F. Padovan 
4074ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40750a708f8fSGustavo F. Padovan 
40762d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40772d792818SGustavo Padovan 			       sizeof(info), &info);
40780a708f8fSGustavo F. Padovan 	}
40790a708f8fSGustavo F. Padovan 
4080c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40810a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
40820a708f8fSGustavo F. Padovan 		u8 buf[128];
4083c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
40840a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
408573ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
408673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40870a708f8fSGustavo F. Padovan 	}
40881700915fSMat Martineau 
40891700915fSMat Martineau 	return chan;
40904c89b6aaSMat Martineau }
40910a708f8fSGustavo F. Padovan 
40924c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4093cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40944c89b6aaSMat Martineau {
40957b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
40967b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
40977b064edaSJaganath Kanakkassery 
4098cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4099cb3b3152SJohan Hedberg 		return -EPROTO;
4100cb3b3152SJohan Hedberg 
41017b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
41027b064edaSJaganath Kanakkassery 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
41037b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
41047b064edaSJaganath Kanakkassery 		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
41057b064edaSJaganath Kanakkassery 				      hcon->dst_type, 0, NULL, 0,
41067b064edaSJaganath Kanakkassery 				      hcon->dev_class);
41077b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
41087b064edaSJaganath Kanakkassery 
4109300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
41100a708f8fSGustavo F. Padovan 	return 0;
41110a708f8fSGustavo F. Padovan }
41120a708f8fSGustavo F. Padovan 
41135909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4114cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4115cb3b3152SJohan Hedberg 				    u8 *data)
41160a708f8fSGustavo F. Padovan {
41170a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
41180a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
411948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
41200a708f8fSGustavo F. Padovan 	u8 req[128];
41213df91ea2SAndrei Emeltchenko 	int err;
41220a708f8fSGustavo F. Padovan 
4123cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4124cb3b3152SJohan Hedberg 		return -EPROTO;
4125cb3b3152SJohan Hedberg 
41260a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
41270a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
41280a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
41290a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
41300a708f8fSGustavo F. Padovan 
41311b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
41321b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
41330a708f8fSGustavo F. Padovan 
41343df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41353df91ea2SAndrei Emeltchenko 
41360a708f8fSGustavo F. Padovan 	if (scid) {
41373df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
41383df91ea2SAndrei Emeltchenko 		if (!chan) {
413921870b52SJohan Hedberg 			err = -EBADSLT;
41403df91ea2SAndrei Emeltchenko 			goto unlock;
41413df91ea2SAndrei Emeltchenko 		}
41420a708f8fSGustavo F. Padovan 	} else {
41433df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
41443df91ea2SAndrei Emeltchenko 		if (!chan) {
414521870b52SJohan Hedberg 			err = -EBADSLT;
41463df91ea2SAndrei Emeltchenko 			goto unlock;
41473df91ea2SAndrei Emeltchenko 		}
41480a708f8fSGustavo F. Padovan 	}
41490a708f8fSGustavo F. Padovan 
41503df91ea2SAndrei Emeltchenko 	err = 0;
41513df91ea2SAndrei Emeltchenko 
41526be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
415348454079SGustavo F. Padovan 
41540a708f8fSGustavo F. Padovan 	switch (result) {
41550a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
415689bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4157fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4158fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4159c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41600a708f8fSGustavo F. Padovan 
4161c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41620a708f8fSGustavo F. Padovan 			break;
41630a708f8fSGustavo F. Padovan 
41640a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
416573ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, req), req);
416673ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41670a708f8fSGustavo F. Padovan 		break;
41680a708f8fSGustavo F. Padovan 
41690a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4170c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41710a708f8fSGustavo F. Padovan 		break;
41720a708f8fSGustavo F. Padovan 
41730a708f8fSGustavo F. Padovan 	default:
417448454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
41750a708f8fSGustavo F. Padovan 		break;
41760a708f8fSGustavo F. Padovan 	}
41770a708f8fSGustavo F. Padovan 
41786be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
41793df91ea2SAndrei Emeltchenko 
41803df91ea2SAndrei Emeltchenko unlock:
41813df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
41823df91ea2SAndrei Emeltchenko 
41833df91ea2SAndrei Emeltchenko 	return err;
41840a708f8fSGustavo F. Padovan }
41850a708f8fSGustavo F. Padovan 
418647d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41870a708f8fSGustavo F. Padovan {
41880a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
41890a708f8fSGustavo F. Padovan 	 * sides request it.
41900a708f8fSGustavo F. Padovan 	 */
41910c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
419247d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4193f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
419447d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
41950a708f8fSGustavo F. Padovan }
41960a708f8fSGustavo F. Padovan 
419729d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
419829d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
419929d8a590SAndrei Emeltchenko {
420029d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
420129d8a590SAndrei Emeltchenko 
420229d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
420329d8a590SAndrei Emeltchenko 	       flags);
420429d8a590SAndrei Emeltchenko 
420529d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
420629d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
420729d8a590SAndrei Emeltchenko 
420829d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
420929d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
421029d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
421129d8a590SAndrei Emeltchenko }
421229d8a590SAndrei Emeltchenko 
4213662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4214662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4215662d652dSJohan Hedberg {
4216662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4217662d652dSJohan Hedberg 
4218662d652dSJohan Hedberg 	rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
4219662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4220662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4221662d652dSJohan Hedberg 
4222662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4223662d652dSJohan Hedberg }
4224662d652dSJohan Hedberg 
42252d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
42262d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
42272d792818SGustavo Padovan 				   u8 *data)
42280a708f8fSGustavo F. Padovan {
42290a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
42300a708f8fSGustavo F. Padovan 	u16 dcid, flags;
42310a708f8fSGustavo F. Padovan 	u8 rsp[64];
423248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42333c588192SMat Martineau 	int len, err = 0;
42340a708f8fSGustavo F. Padovan 
4235cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4236cb3b3152SJohan Hedberg 		return -EPROTO;
4237cb3b3152SJohan Hedberg 
42380a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
42390a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
42400a708f8fSGustavo F. Padovan 
42410a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42420a708f8fSGustavo F. Padovan 
4243baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4244662d652dSJohan Hedberg 	if (!chan) {
4245662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4246662d652dSJohan Hedberg 		return 0;
4247662d652dSJohan Hedberg 	}
42480a708f8fSGustavo F. Padovan 
4249033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4250662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4251662d652dSJohan Hedberg 				       chan->dcid);
42520a708f8fSGustavo F. Padovan 		goto unlock;
42530a708f8fSGustavo F. Padovan 	}
42540a708f8fSGustavo F. Padovan 
42550a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
42560a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4257cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
42580a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4259fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42600a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
42610a708f8fSGustavo F. Padovan 		goto unlock;
42620a708f8fSGustavo F. Padovan 	}
42630a708f8fSGustavo F. Padovan 
42640a708f8fSGustavo F. Padovan 	/* Store config. */
426573ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
426673ffa904SGustavo F. Padovan 	chan->conf_len += len;
42670a708f8fSGustavo F. Padovan 
426859e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42690a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
42700a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4271fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42725325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
42730a708f8fSGustavo F. Padovan 		goto unlock;
42740a708f8fSGustavo F. Padovan 	}
42750a708f8fSGustavo F. Padovan 
42760a708f8fSGustavo F. Padovan 	/* Complete config. */
427773ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
42780a708f8fSGustavo F. Padovan 	if (len < 0) {
42795e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42800a708f8fSGustavo F. Padovan 		goto unlock;
42810a708f8fSGustavo F. Padovan 	}
42820a708f8fSGustavo F. Padovan 
42831500109bSMat Martineau 	chan->ident = cmd->ident;
42840a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
428573ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
42860a708f8fSGustavo F. Padovan 
42870a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
428873ffa904SGustavo F. Padovan 	chan->conf_len = 0;
42890a708f8fSGustavo F. Padovan 
4290c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42910a708f8fSGustavo F. Padovan 		goto unlock;
42920a708f8fSGustavo F. Padovan 
4293c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
429447d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
42950a708f8fSGustavo F. Padovan 
4296105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4297105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
42983c588192SMat Martineau 			err = l2cap_ertm_init(chan);
42990a708f8fSGustavo F. Padovan 
43003c588192SMat Martineau 		if (err < 0)
43015e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
43023c588192SMat Martineau 		else
4303cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
43043c588192SMat Martineau 
43050a708f8fSGustavo F. Padovan 		goto unlock;
43060a708f8fSGustavo F. Padovan 	}
43070a708f8fSGustavo F. Padovan 
4308c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
43090a708f8fSGustavo F. Padovan 		u8 buf[64];
43100a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
431173ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
431273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43130a708f8fSGustavo F. Padovan 	}
43140a708f8fSGustavo F. Padovan 
43150e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
43160e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
43170e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
43180e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43190e8b207eSAndrei Emeltchenko 
43200e8b207eSAndrei Emeltchenko 		/* check compatibility */
43210e8b207eSAndrei Emeltchenko 
432279de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4323f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
432429d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
432579de886dSAndrei Emeltchenko 		else
432679de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
43270e8b207eSAndrei Emeltchenko 	}
43280e8b207eSAndrei Emeltchenko 
43290a708f8fSGustavo F. Padovan unlock:
43306be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43313c588192SMat Martineau 	return err;
43320a708f8fSGustavo F. Padovan }
43330a708f8fSGustavo F. Padovan 
43342d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4335cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4336cb3b3152SJohan Hedberg 				   u8 *data)
43370a708f8fSGustavo F. Padovan {
43380a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43390a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
434048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4341cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
43423c588192SMat Martineau 	int err = 0;
43430a708f8fSGustavo F. Padovan 
4344cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4345cb3b3152SJohan Hedberg 		return -EPROTO;
4346cb3b3152SJohan Hedberg 
43470a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
43480a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
43490a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
43500a708f8fSGustavo F. Padovan 
435161386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
435261386cbaSAndrei Emeltchenko 	       result, len);
43530a708f8fSGustavo F. Padovan 
4354baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
435548454079SGustavo F. Padovan 	if (!chan)
43560a708f8fSGustavo F. Padovan 		return 0;
43570a708f8fSGustavo F. Padovan 
43580a708f8fSGustavo F. Padovan 	switch (result) {
43590a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
436047d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
43610e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43620a708f8fSGustavo F. Padovan 		break;
43630a708f8fSGustavo F. Padovan 
43640e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
43650e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43660e8b207eSAndrei Emeltchenko 
43670e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43680e8b207eSAndrei Emeltchenko 			char buf[64];
43690e8b207eSAndrei Emeltchenko 
43700e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
43710e8b207eSAndrei Emeltchenko 						   buf, &result);
43720e8b207eSAndrei Emeltchenko 			if (len < 0) {
43735e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43740e8b207eSAndrei Emeltchenko 				goto done;
43750e8b207eSAndrei Emeltchenko 			}
43760e8b207eSAndrei Emeltchenko 
4377f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
437879de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
437979de886dSAndrei Emeltchenko 							0);
43805ce66b59SAndrei Emeltchenko 			} else {
43815ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
43825ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
438379de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
43840e8b207eSAndrei Emeltchenko 				}
43855ce66b59SAndrei Emeltchenko 			}
43865ce66b59SAndrei Emeltchenko 		}
43870e8b207eSAndrei Emeltchenko 		goto done;
43880e8b207eSAndrei Emeltchenko 
43890a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
439073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43910a708f8fSGustavo F. Padovan 			char req[64];
43920a708f8fSGustavo F. Padovan 
43930a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43945e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43950a708f8fSGustavo F. Padovan 				goto done;
43960a708f8fSGustavo F. Padovan 			}
43970a708f8fSGustavo F. Padovan 
43980a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
43990a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4400b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4401b4450035SGustavo F. Padovan 						   req, &result);
44020a708f8fSGustavo F. Padovan 			if (len < 0) {
44035e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
44040a708f8fSGustavo F. Padovan 				goto done;
44050a708f8fSGustavo F. Padovan 			}
44060a708f8fSGustavo F. Padovan 
44070a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
44080a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
440973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
44100a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
44110a708f8fSGustavo F. Padovan 				goto done;
44120a708f8fSGustavo F. Padovan 			break;
44130a708f8fSGustavo F. Padovan 		}
44140a708f8fSGustavo F. Padovan 
44150a708f8fSGustavo F. Padovan 	default:
44166be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
44172e0052e4SAndrei Emeltchenko 
4418ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
44195e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
44200a708f8fSGustavo F. Padovan 		goto done;
44210a708f8fSGustavo F. Padovan 	}
44220a708f8fSGustavo F. Padovan 
442359e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
44240a708f8fSGustavo F. Padovan 		goto done;
44250a708f8fSGustavo F. Padovan 
4426c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
44270a708f8fSGustavo F. Padovan 
4428c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
442947d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44300a708f8fSGustavo F. Padovan 
4431105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4432105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44333c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44340a708f8fSGustavo F. Padovan 
44353c588192SMat Martineau 		if (err < 0)
44365e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44373c588192SMat Martineau 		else
4438cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44390a708f8fSGustavo F. Padovan 	}
44400a708f8fSGustavo F. Padovan 
44410a708f8fSGustavo F. Padovan done:
44426be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44433c588192SMat Martineau 	return err;
44440a708f8fSGustavo F. Padovan }
44450a708f8fSGustavo F. Padovan 
44462d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4447cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4448cb3b3152SJohan Hedberg 				       u8 *data)
44490a708f8fSGustavo F. Padovan {
44500a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44510a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
44520a708f8fSGustavo F. Padovan 	u16 dcid, scid;
445348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44540a708f8fSGustavo F. Padovan 
4455cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4456cb3b3152SJohan Hedberg 		return -EPROTO;
4457cb3b3152SJohan Hedberg 
44580a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
44590a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
44600a708f8fSGustavo F. Padovan 
44610a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44620a708f8fSGustavo F. Padovan 
44633df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
44643df91ea2SAndrei Emeltchenko 
44653df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
44663df91ea2SAndrei Emeltchenko 	if (!chan) {
44673df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4468662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4469662d652dSJohan Hedberg 		return 0;
44703df91ea2SAndrei Emeltchenko 	}
44710a708f8fSGustavo F. Padovan 
44726be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
44736be36555SAndrei Emeltchenko 
4474fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4475fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
44760a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44770a708f8fSGustavo F. Padovan 
44785ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
44790a708f8fSGustavo F. Padovan 
448061d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
448148454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
44826be36555SAndrei Emeltchenko 
44836be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44840a708f8fSGustavo F. Padovan 
448580b98027SGustavo Padovan 	chan->ops->close(chan);
448661d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44873df91ea2SAndrei Emeltchenko 
44883df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
44893df91ea2SAndrei Emeltchenko 
44900a708f8fSGustavo F. Padovan 	return 0;
44910a708f8fSGustavo F. Padovan }
44920a708f8fSGustavo F. Padovan 
44932d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4494cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4495cb3b3152SJohan Hedberg 				       u8 *data)
44960a708f8fSGustavo F. Padovan {
44970a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44980a708f8fSGustavo F. Padovan 	u16 dcid, scid;
449948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
45000a708f8fSGustavo F. Padovan 
4501cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4502cb3b3152SJohan Hedberg 		return -EPROTO;
4503cb3b3152SJohan Hedberg 
45040a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
45050a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
45060a708f8fSGustavo F. Padovan 
45070a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
45080a708f8fSGustavo F. Padovan 
45093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
45103df91ea2SAndrei Emeltchenko 
45113df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
45123df91ea2SAndrei Emeltchenko 	if (!chan) {
45133df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
45140a708f8fSGustavo F. Padovan 		return 0;
45153df91ea2SAndrei Emeltchenko 	}
45160a708f8fSGustavo F. Padovan 
45176be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
451848454079SGustavo F. Padovan 
451961d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
452048454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
45216be36555SAndrei Emeltchenko 
45226be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45230a708f8fSGustavo F. Padovan 
452480b98027SGustavo Padovan 	chan->ops->close(chan);
452561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
45263df91ea2SAndrei Emeltchenko 
45273df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
45283df91ea2SAndrei Emeltchenko 
45290a708f8fSGustavo F. Padovan 	return 0;
45300a708f8fSGustavo F. Padovan }
45310a708f8fSGustavo F. Padovan 
45322d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4533cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4534cb3b3152SJohan Hedberg 					u8 *data)
45350a708f8fSGustavo F. Padovan {
45360a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
45370a708f8fSGustavo F. Padovan 	u16 type;
45380a708f8fSGustavo F. Padovan 
4539cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4540cb3b3152SJohan Hedberg 		return -EPROTO;
4541cb3b3152SJohan Hedberg 
45420a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
45430a708f8fSGustavo F. Padovan 
45440a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
45450a708f8fSGustavo F. Padovan 
45460a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
45470a708f8fSGustavo F. Padovan 		u8 buf[8];
45480a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
45490a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4550ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
4551ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
45520a708f8fSGustavo F. Padovan 		if (!disable_ertm)
45530a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45540a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
4555848566b3SMarcel Holtmann 		if (conn->hs_enabled)
45566327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
45576327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4558a5fd6f30SAndrei Emeltchenko 
45590a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
45602d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45612d792818SGustavo Padovan 			       buf);
45620a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
45630a708f8fSGustavo F. Padovan 		u8 buf[12];
45640a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
456550a147cdSMat Martineau 
4566848566b3SMarcel Holtmann 		if (conn->hs_enabled)
456750a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
456850a147cdSMat Martineau 		else
456950a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
457050a147cdSMat Martineau 
4571ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4572ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
4573c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
45742d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45752d792818SGustavo Padovan 			       buf);
45760a708f8fSGustavo F. Padovan 	} else {
45770a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
45780a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4579ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
45802d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45812d792818SGustavo Padovan 			       &rsp);
45820a708f8fSGustavo F. Padovan 	}
45830a708f8fSGustavo F. Padovan 
45840a708f8fSGustavo F. Padovan 	return 0;
45850a708f8fSGustavo F. Padovan }
45860a708f8fSGustavo F. Padovan 
45872d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4588cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4589cb3b3152SJohan Hedberg 					u8 *data)
45900a708f8fSGustavo F. Padovan {
45910a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45920a708f8fSGustavo F. Padovan 	u16 type, result;
45930a708f8fSGustavo F. Padovan 
45943f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4595cb3b3152SJohan Hedberg 		return -EPROTO;
4596cb3b3152SJohan Hedberg 
45970a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
45980a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
45990a708f8fSGustavo F. Padovan 
46000a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
46010a708f8fSGustavo F. Padovan 
4602e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4603e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4604e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4605e90165beSAndrei Emeltchenko 		return 0;
4606e90165beSAndrei Emeltchenko 
460717cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
46080a708f8fSGustavo F. Padovan 
46090a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
46100a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46110a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46120a708f8fSGustavo F. Padovan 
46130a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
46140a708f8fSGustavo F. Padovan 
46150a708f8fSGustavo F. Padovan 		return 0;
46160a708f8fSGustavo F. Padovan 	}
46170a708f8fSGustavo F. Padovan 
4618978c93b9SAndrei Emeltchenko 	switch (type) {
4619978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
46200a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
46210a708f8fSGustavo F. Padovan 
46220a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
46230a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4624ac73498cSAndrei Emeltchenko 			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
46250a708f8fSGustavo F. Padovan 
46260a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
46270a708f8fSGustavo F. Padovan 
46280a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
46290a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
46300a708f8fSGustavo F. Padovan 		} else {
46310a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46320a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
46330a708f8fSGustavo F. Padovan 
46340a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
46350a708f8fSGustavo F. Padovan 		}
4636978c93b9SAndrei Emeltchenko 		break;
4637978c93b9SAndrei Emeltchenko 
4638978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
4639978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
46400a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46410a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46420a708f8fSGustavo F. Padovan 
46430a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4644978c93b9SAndrei Emeltchenko 		break;
46450a708f8fSGustavo F. Padovan 	}
46460a708f8fSGustavo F. Padovan 
46470a708f8fSGustavo F. Padovan 	return 0;
46480a708f8fSGustavo F. Padovan }
46490a708f8fSGustavo F. Padovan 
46501700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
46512d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
46522d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4653f94ff6ffSMat Martineau {
4654f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
46556e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
46561700915fSMat Martineau 	struct l2cap_chan *chan;
46576e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4658f94ff6ffSMat Martineau 	u16 psm, scid;
4659f94ff6ffSMat Martineau 
4660f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4661f94ff6ffSMat Martineau 		return -EPROTO;
4662f94ff6ffSMat Martineau 
4663848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
4664f94ff6ffSMat Martineau 		return -EINVAL;
4665f94ff6ffSMat Martineau 
4666f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4667f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4668f94ff6ffSMat Martineau 
4669ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4670f94ff6ffSMat Martineau 
46716e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
46726ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
46736e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46746e1df6a6SAndrei Emeltchenko 			      req->amp_id);
46756e1df6a6SAndrei Emeltchenko 		return 0;
46766e1df6a6SAndrei Emeltchenko 	}
46771700915fSMat Martineau 
46781700915fSMat Martineau 	/* Validate AMP controller id */
46791700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
46806e1df6a6SAndrei Emeltchenko 	if (!hdev)
46816e1df6a6SAndrei Emeltchenko 		goto error;
46821700915fSMat Martineau 
46836e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
46846e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
46856e1df6a6SAndrei Emeltchenko 		goto error;
46866e1df6a6SAndrei Emeltchenko 	}
46876e1df6a6SAndrei Emeltchenko 
46886e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46896e1df6a6SAndrei Emeltchenko 			     req->amp_id);
46906e1df6a6SAndrei Emeltchenko 	if (chan) {
46916e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
46926e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
46936e1df6a6SAndrei Emeltchenko 
469498e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
469598e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
46966e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
46976e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4698662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4699662d652dSJohan Hedberg 					       chan->dcid);
4700662d652dSJohan Hedberg 			return 0;
47016e1df6a6SAndrei Emeltchenko 		}
47026e1df6a6SAndrei Emeltchenko 
47036e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
47046e1df6a6SAndrei Emeltchenko 
47056e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
47066e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4707fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
47086e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
47096e1df6a6SAndrei Emeltchenko 	}
47106e1df6a6SAndrei Emeltchenko 
47116e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
47126e1df6a6SAndrei Emeltchenko 
47136e1df6a6SAndrei Emeltchenko 	return 0;
47146e1df6a6SAndrei Emeltchenko 
47156e1df6a6SAndrei Emeltchenko error:
4716f94ff6ffSMat Martineau 	rsp.dcid = 0;
4717f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
47181700915fSMat Martineau 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
47198ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4720f94ff6ffSMat Martineau 
4721f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4722f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4723f94ff6ffSMat Martineau 
4724dc280801SJohan Hedberg 	return 0;
4725f94ff6ffSMat Martineau }
4726f94ff6ffSMat Martineau 
47278eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
47288eb200bdSMat Martineau {
47298eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
47308eb200bdSMat Martineau 	u8 ident;
47318eb200bdSMat Martineau 
47328eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
47338eb200bdSMat Martineau 
47348eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
47358eb200bdSMat Martineau 	chan->ident = ident;
47368eb200bdSMat Martineau 
47378eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
47388eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
47398eb200bdSMat Martineau 
47408eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
47418eb200bdSMat Martineau 		       &req);
47428eb200bdSMat Martineau 
47438eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47448eb200bdSMat Martineau }
47458eb200bdSMat Martineau 
47461500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
47478d5a04a1SMat Martineau {
47488d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
47498d5a04a1SMat Martineau 
47501500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47518d5a04a1SMat Martineau 
47521500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
47538d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
47548d5a04a1SMat Martineau 
47551500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
47561500109bSMat Martineau 		       sizeof(rsp), &rsp);
47578d5a04a1SMat Martineau }
47588d5a04a1SMat Martineau 
47595b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
47608d5a04a1SMat Martineau {
47618d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47628d5a04a1SMat Martineau 
47635b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47648d5a04a1SMat Martineau 
47655b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
47668d5a04a1SMat Martineau 
47675b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
47688d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
47698d5a04a1SMat Martineau 
47705b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
47715b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47725b155ef9SMat Martineau 
47735b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47745b155ef9SMat Martineau }
47755b155ef9SMat Martineau 
47765b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
47775b155ef9SMat Martineau {
47785b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47795b155ef9SMat Martineau 
47805b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
47815b155ef9SMat Martineau 
47825b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
47835b155ef9SMat Martineau 	cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
47845b155ef9SMat Martineau 
47855b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
47865b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47878d5a04a1SMat Martineau }
47888d5a04a1SMat Martineau 
47898d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
47908d5a04a1SMat Martineau 					 u16 icid)
47918d5a04a1SMat Martineau {
47928d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
47938d5a04a1SMat Martineau 
4794ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
47958d5a04a1SMat Martineau 
47968d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
47978d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
47988d5a04a1SMat Martineau }
47998d5a04a1SMat Martineau 
48005f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
48015f3847a4SMat Martineau {
48025f3847a4SMat Martineau 	chan->hs_hchan = NULL;
48035f3847a4SMat Martineau 	chan->hs_hcon = NULL;
48045f3847a4SMat Martineau 
48055f3847a4SMat Martineau 	/* Placeholder - release the logical link */
48065f3847a4SMat Martineau }
48075f3847a4SMat Martineau 
48081500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
48091500109bSMat Martineau {
48101500109bSMat Martineau 	/* Logical link setup failed */
48111500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
48121500109bSMat Martineau 		/* Create channel failure, disconnect */
48135e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
48141500109bSMat Martineau 		return;
48151500109bSMat Martineau 	}
48161500109bSMat Martineau 
48171500109bSMat Martineau 	switch (chan->move_role) {
48181500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
48191500109bSMat Martineau 		l2cap_move_done(chan);
48201500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
48211500109bSMat Martineau 		break;
48221500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
48231500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
48241500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
48251500109bSMat Martineau 			/* Remote has only sent pending or
48261500109bSMat Martineau 			 * success responses, clean up
48271500109bSMat Martineau 			 */
48281500109bSMat Martineau 			l2cap_move_done(chan);
48291500109bSMat Martineau 		}
48301500109bSMat Martineau 
48311500109bSMat Martineau 		/* Other amp move states imply that the move
48321500109bSMat Martineau 		 * has already aborted
48331500109bSMat Martineau 		 */
48341500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
48351500109bSMat Martineau 		break;
48361500109bSMat Martineau 	}
48371500109bSMat Martineau }
48381500109bSMat Martineau 
48391500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
48401500109bSMat Martineau 					struct hci_chan *hchan)
48411500109bSMat Martineau {
48421500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
48431500109bSMat Martineau 
4844336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
48451500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48461500109bSMat Martineau 
484735ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
48481500109bSMat Martineau 
48491500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4850fe79c6feSAndrei Emeltchenko 		int err;
48511500109bSMat Martineau 
48521500109bSMat Martineau 		set_default_fcs(chan);
48531500109bSMat Martineau 
48541500109bSMat Martineau 		err = l2cap_ertm_init(chan);
48551500109bSMat Martineau 		if (err < 0)
48565e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
48571500109bSMat Martineau 		else
48581500109bSMat Martineau 			l2cap_chan_ready(chan);
48591500109bSMat Martineau 	}
48601500109bSMat Martineau }
48611500109bSMat Martineau 
48621500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
48631500109bSMat Martineau 				      struct hci_chan *hchan)
48641500109bSMat Martineau {
48651500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
48661500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48671500109bSMat Martineau 
48681500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
48691500109bSMat Martineau 
48701500109bSMat Martineau 	switch (chan->move_state) {
48711500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
48721500109bSMat Martineau 		/* Move confirm will be sent after a success
48731500109bSMat Martineau 		 * response is received
48741500109bSMat Martineau 		 */
48751500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
48761500109bSMat Martineau 		break;
48771500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
48781500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
48791500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
48801500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
48811500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
48821500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
48831500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
48841500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48851500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48861500109bSMat Martineau 		}
48871500109bSMat Martineau 		break;
48881500109bSMat Martineau 	default:
48891500109bSMat Martineau 		/* Move was not in expected state, free the channel */
48901500109bSMat Martineau 		__release_logical_link(chan);
48911500109bSMat Martineau 
48921500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
48931500109bSMat Martineau 	}
48941500109bSMat Martineau }
48951500109bSMat Martineau 
48961500109bSMat Martineau /* Call with chan locked */
489727695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
48985b155ef9SMat Martineau 		       u8 status)
48995b155ef9SMat Martineau {
49001500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
49011500109bSMat Martineau 
49021500109bSMat Martineau 	if (status) {
49031500109bSMat Martineau 		l2cap_logical_fail(chan);
49041500109bSMat Martineau 		__release_logical_link(chan);
49055b155ef9SMat Martineau 		return;
49065b155ef9SMat Martineau 	}
49075b155ef9SMat Martineau 
49081500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
49091500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
49106ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
49111500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
49121500109bSMat Martineau 	} else {
49131500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
49141500109bSMat Martineau 	}
49151500109bSMat Martineau }
49161500109bSMat Martineau 
49173f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
49183f7a56c4SMat Martineau {
49193f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
49203f7a56c4SMat Martineau 
49216ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
49223f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
49233f7a56c4SMat Martineau 			return;
49243f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49253f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
49263f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
49273f7a56c4SMat Martineau 	} else {
49283f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49293f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
49303f7a56c4SMat Martineau 		chan->move_id = 0;
49313f7a56c4SMat Martineau 		l2cap_move_setup(chan);
49323f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
49333f7a56c4SMat Martineau 	}
49343f7a56c4SMat Martineau }
49353f7a56c4SMat Martineau 
49368eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
49378eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
49388eb200bdSMat Martineau {
493962748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
494062748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
494162748ca1SAndrei Emeltchenko 
494212d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
494312d6cc60SAndrei Emeltchenko 
494462748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
494562748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
494662748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
494762748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
494862748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
494962748ca1SAndrei Emeltchenko 		} else {
495062748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
495162748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
495262748ca1SAndrei Emeltchenko 		}
495362748ca1SAndrei Emeltchenko 
495462748ca1SAndrei Emeltchenko 		return;
495562748ca1SAndrei Emeltchenko 	}
495662748ca1SAndrei Emeltchenko 
495762748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
495862748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
49598eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
49608eb200bdSMat Martineau 		char buf[128];
49618eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
49628eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
49638eb200bdSMat Martineau 
49648eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
49658eb200bdSMat Martineau 			/* Send successful response */
496662cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
496762cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49688eb200bdSMat Martineau 		} else {
49698eb200bdSMat Martineau 			/* Send negative response */
497062cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
497162cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49728eb200bdSMat Martineau 		}
49738eb200bdSMat Martineau 
49748eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
49758eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
49768eb200bdSMat Martineau 
49778eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4978f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
49798eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
49808eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
49818eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
49828eb200bdSMat Martineau 				       l2cap_build_conf_req(chan, buf), buf);
49838eb200bdSMat Martineau 			chan->num_conf_req++;
49848eb200bdSMat Martineau 		}
49858eb200bdSMat Martineau 	}
49868eb200bdSMat Martineau }
49878eb200bdSMat Martineau 
49888eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
49898eb200bdSMat Martineau 				   u8 remote_amp_id)
49908eb200bdSMat Martineau {
49918eb200bdSMat Martineau 	l2cap_move_setup(chan);
49928eb200bdSMat Martineau 	chan->move_id = local_amp_id;
49938eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
49948eb200bdSMat Martineau 
49958eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
49968eb200bdSMat Martineau }
49978eb200bdSMat Martineau 
49988eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
49998eb200bdSMat Martineau {
50008eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
50018eb200bdSMat Martineau 
50028eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
50038eb200bdSMat Martineau 
50048eb200bdSMat Martineau 	if (hchan) {
50058eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
50068eb200bdSMat Martineau 			/* Logical link is ready to go */
50078eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
50088eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
50098eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
50108eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
50118eb200bdSMat Martineau 
50128eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
50138eb200bdSMat Martineau 		} else {
50148eb200bdSMat Martineau 			/* Wait for logical link to be ready */
50158eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50168eb200bdSMat Martineau 		}
50178eb200bdSMat Martineau 	} else {
50188eb200bdSMat Martineau 		/* Logical link not available */
50198eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
50208eb200bdSMat Martineau 	}
50218eb200bdSMat Martineau }
50228eb200bdSMat Martineau 
50238eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
50248eb200bdSMat Martineau {
50258eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50268eb200bdSMat Martineau 		u8 rsp_result;
50278eb200bdSMat Martineau 		if (result == -EINVAL)
50288eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
50298eb200bdSMat Martineau 		else
50308eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
50318eb200bdSMat Martineau 
50328eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
50338eb200bdSMat Martineau 	}
50348eb200bdSMat Martineau 
50358eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
50368eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
50378eb200bdSMat Martineau 
50388eb200bdSMat Martineau 	/* Restart data transmission */
50398eb200bdSMat Martineau 	l2cap_ertm_send(chan);
50408eb200bdSMat Martineau }
50418eb200bdSMat Martineau 
5042a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5043a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
50448eb200bdSMat Martineau {
5045770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5046fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5047770bfefaSAndrei Emeltchenko 
50488eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
50498eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
50508eb200bdSMat Martineau 
50518eb200bdSMat Martineau 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
50528eb200bdSMat Martineau 		l2cap_chan_unlock(chan);
50538eb200bdSMat Martineau 		return;
50548eb200bdSMat Martineau 	}
50558eb200bdSMat Martineau 
50568eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
50578eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
50588eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
50598eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
50608eb200bdSMat Martineau 	} else {
50618eb200bdSMat Martineau 		switch (chan->move_role) {
50628eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
50638eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
50648eb200bdSMat Martineau 					       remote_amp_id);
50658eb200bdSMat Martineau 			break;
50668eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
50678eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
50688eb200bdSMat Martineau 			break;
50698eb200bdSMat Martineau 		default:
50708eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
50718eb200bdSMat Martineau 			break;
50728eb200bdSMat Martineau 		}
50738eb200bdSMat Martineau 	}
50748eb200bdSMat Martineau }
50758eb200bdSMat Martineau 
50768d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5077ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5078ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
50798d5a04a1SMat Martineau {
50808d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
50811500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
508202b0fbb9SMat Martineau 	struct l2cap_chan *chan;
50838d5a04a1SMat Martineau 	u16 icid = 0;
50848d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
50858d5a04a1SMat Martineau 
50868d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
50878d5a04a1SMat Martineau 		return -EPROTO;
50888d5a04a1SMat Martineau 
50898d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
50908d5a04a1SMat Martineau 
5091ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
50928d5a04a1SMat Martineau 
5093848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
50948d5a04a1SMat Martineau 		return -EINVAL;
50958d5a04a1SMat Martineau 
509602b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
509702b0fbb9SMat Martineau 	if (!chan) {
50981500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
50991500109bSMat Martineau 		rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
51001500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
51011500109bSMat Martineau 			       sizeof(rsp), &rsp);
510202b0fbb9SMat Martineau 		return 0;
510302b0fbb9SMat Martineau 	}
510402b0fbb9SMat Martineau 
51051500109bSMat Martineau 	chan->ident = cmd->ident;
51061500109bSMat Martineau 
510702b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
510802b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
510902b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
511002b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
511102b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
511202b0fbb9SMat Martineau 		goto send_move_response;
511302b0fbb9SMat Martineau 	}
511402b0fbb9SMat Martineau 
511502b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
511602b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
511702b0fbb9SMat Martineau 		goto send_move_response;
511802b0fbb9SMat Martineau 	}
511902b0fbb9SMat Martineau 
51206ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
512102b0fbb9SMat Martineau 		struct hci_dev *hdev;
512202b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
512302b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
512402b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
512502b0fbb9SMat Martineau 			if (hdev)
512602b0fbb9SMat Martineau 				hci_dev_put(hdev);
512702b0fbb9SMat Martineau 
512802b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
512902b0fbb9SMat Martineau 			goto send_move_response;
513002b0fbb9SMat Martineau 		}
513102b0fbb9SMat Martineau 		hci_dev_put(hdev);
513202b0fbb9SMat Martineau 	}
513302b0fbb9SMat Martineau 
513402b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
513502b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
513602b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
513702b0fbb9SMat Martineau 	 */
513802b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
513902b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
51406f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
514102b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
514202b0fbb9SMat Martineau 		goto send_move_response;
514302b0fbb9SMat Martineau 	}
514402b0fbb9SMat Martineau 
514502b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
514602b0fbb9SMat Martineau 	l2cap_move_setup(chan);
514702b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
514802b0fbb9SMat Martineau 	icid = chan->dcid;
514902b0fbb9SMat Martineau 
51506ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
515102b0fbb9SMat Martineau 		/* Moving to BR/EDR */
515202b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
515302b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
515402b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
515502b0fbb9SMat Martineau 		} else {
515602b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
515702b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
515802b0fbb9SMat Martineau 		}
515902b0fbb9SMat Martineau 	} else {
516002b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
516102b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
516202b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
516302b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
516402b0fbb9SMat Martineau 	}
516502b0fbb9SMat Martineau 
516602b0fbb9SMat Martineau send_move_response:
51671500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
51688d5a04a1SMat Martineau 
516902b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
517002b0fbb9SMat Martineau 
51718d5a04a1SMat Martineau 	return 0;
51728d5a04a1SMat Martineau }
51738d5a04a1SMat Martineau 
51745b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
51755b155ef9SMat Martineau {
51765b155ef9SMat Martineau 	struct l2cap_chan *chan;
51775b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
51785b155ef9SMat Martineau 
51795b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
51805b155ef9SMat Martineau 	if (!chan) {
51815b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51825b155ef9SMat Martineau 		return;
51835b155ef9SMat Martineau 	}
51845b155ef9SMat Martineau 
51855b155ef9SMat Martineau 	__clear_chan_timer(chan);
51865b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
51875b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
51885b155ef9SMat Martineau 
51895b155ef9SMat Martineau 	switch (chan->move_state) {
51905b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
51915b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
51925b155ef9SMat Martineau 		 * is complete.
51935b155ef9SMat Martineau 		 */
51945b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51955b155ef9SMat Martineau 		break;
51965b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
51975b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
51985b155ef9SMat Martineau 			break;
51995b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
52005b155ef9SMat Martineau 				    &chan->conn_state)) {
52015b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
52025b155ef9SMat Martineau 		} else {
52035b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
52045b155ef9SMat Martineau 			 * proceed with move
52055b155ef9SMat Martineau 			 */
52065b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
52075b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
52085b155ef9SMat Martineau 		}
52095b155ef9SMat Martineau 		break;
52105b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
52115b155ef9SMat Martineau 		/* Moving to AMP */
52125b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
52135b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
52145b155ef9SMat Martineau 			 * after logical link is ready
52155b155ef9SMat Martineau 			 */
52165b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
52175b155ef9SMat Martineau 		} else {
52185b155ef9SMat Martineau 			/* Both logical link and move success
52195b155ef9SMat Martineau 			 * are required to confirm
52205b155ef9SMat Martineau 			 */
52215b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
52225b155ef9SMat Martineau 		}
52235b155ef9SMat Martineau 
52245b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
52255b155ef9SMat Martineau 		if (!hchan) {
52265b155ef9SMat Martineau 			/* Logical link not available */
52275b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52285b155ef9SMat Martineau 			break;
52295b155ef9SMat Martineau 		}
52305b155ef9SMat Martineau 
52315b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
52325b155ef9SMat Martineau 		 * send confirmation.
52335b155ef9SMat Martineau 		 */
52345b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
52355b155ef9SMat Martineau 			break;
52365b155ef9SMat Martineau 
52375b155ef9SMat Martineau 		/* Logical link is already ready to go */
52385b155ef9SMat Martineau 
52395b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
52405b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
52415b155ef9SMat Martineau 
52425b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
52435b155ef9SMat Martineau 			/* Can confirm now */
52445b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
52455b155ef9SMat Martineau 		} else {
52465b155ef9SMat Martineau 			/* Now only need move success
52475b155ef9SMat Martineau 			 * to confirm
52485b155ef9SMat Martineau 			 */
52495b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
52505b155ef9SMat Martineau 		}
52515b155ef9SMat Martineau 
52525b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
52535b155ef9SMat Martineau 		break;
52545b155ef9SMat Martineau 	default:
52555b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
52565b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
52575b155ef9SMat Martineau 		l2cap_move_done(chan);
52585b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52595b155ef9SMat Martineau 	}
52605b155ef9SMat Martineau 
52615b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52625b155ef9SMat Martineau }
52635b155ef9SMat Martineau 
52645b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
52655b155ef9SMat Martineau 			    u16 result)
52665b155ef9SMat Martineau {
52675b155ef9SMat Martineau 	struct l2cap_chan *chan;
52685b155ef9SMat Martineau 
52695b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
52705b155ef9SMat Martineau 	if (!chan) {
52715b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
52725b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
52735b155ef9SMat Martineau 		return;
52745b155ef9SMat Martineau 	}
52755b155ef9SMat Martineau 
52765b155ef9SMat Martineau 	__clear_chan_timer(chan);
52775b155ef9SMat Martineau 
52785b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
52795b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
52805b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
52815b155ef9SMat Martineau 		} else {
52825b155ef9SMat Martineau 			/* Cleanup - cancel move */
52835b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
52845b155ef9SMat Martineau 			l2cap_move_done(chan);
52855b155ef9SMat Martineau 		}
52865b155ef9SMat Martineau 	}
52875b155ef9SMat Martineau 
52885b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52895b155ef9SMat Martineau 
52905b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52915b155ef9SMat Martineau }
52925b155ef9SMat Martineau 
52935b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5294ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5295ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
52968d5a04a1SMat Martineau {
52978d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
52988d5a04a1SMat Martineau 	u16 icid, result;
52998d5a04a1SMat Martineau 
53008d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
53018d5a04a1SMat Martineau 		return -EPROTO;
53028d5a04a1SMat Martineau 
53038d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
53048d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
53058d5a04a1SMat Martineau 
5306ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
53078d5a04a1SMat Martineau 
53085b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
53095b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
53105b155ef9SMat Martineau 	else
53115b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
53128d5a04a1SMat Martineau 
53138d5a04a1SMat Martineau 	return 0;
53148d5a04a1SMat Martineau }
53158d5a04a1SMat Martineau 
53165f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5317ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5318ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
53198d5a04a1SMat Martineau {
53208d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
53215f3847a4SMat Martineau 	struct l2cap_chan *chan;
53228d5a04a1SMat Martineau 	u16 icid, result;
53238d5a04a1SMat Martineau 
53248d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
53258d5a04a1SMat Martineau 		return -EPROTO;
53268d5a04a1SMat Martineau 
53278d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
53288d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
53298d5a04a1SMat Martineau 
5330ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
53318d5a04a1SMat Martineau 
53325f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
53335f3847a4SMat Martineau 	if (!chan) {
53345f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
53358d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53365f3847a4SMat Martineau 		return 0;
53375f3847a4SMat Martineau 	}
53385f3847a4SMat Martineau 
53395f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
53405f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
53415f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
53426ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
53435f3847a4SMat Martineau 				__release_logical_link(chan);
53445f3847a4SMat Martineau 		} else {
53455f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
53465f3847a4SMat Martineau 		}
53475f3847a4SMat Martineau 
53485f3847a4SMat Martineau 		l2cap_move_done(chan);
53495f3847a4SMat Martineau 	}
53505f3847a4SMat Martineau 
53515f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53525f3847a4SMat Martineau 
53535f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
53548d5a04a1SMat Martineau 
53558d5a04a1SMat Martineau 	return 0;
53568d5a04a1SMat Martineau }
53578d5a04a1SMat Martineau 
53588d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5359ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5360ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
53618d5a04a1SMat Martineau {
53628d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
53633fd71a0aSMat Martineau 	struct l2cap_chan *chan;
53648d5a04a1SMat Martineau 	u16 icid;
53658d5a04a1SMat Martineau 
53668d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
53678d5a04a1SMat Martineau 		return -EPROTO;
53688d5a04a1SMat Martineau 
53698d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
53708d5a04a1SMat Martineau 
5371ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
53728d5a04a1SMat Martineau 
53733fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53743fd71a0aSMat Martineau 	if (!chan)
53753fd71a0aSMat Martineau 		return 0;
53763fd71a0aSMat Martineau 
53773fd71a0aSMat Martineau 	__clear_chan_timer(chan);
53783fd71a0aSMat Martineau 
53793fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
53803fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
53813fd71a0aSMat Martineau 
53826ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
53833fd71a0aSMat Martineau 			__release_logical_link(chan);
53843fd71a0aSMat Martineau 
53853fd71a0aSMat Martineau 		l2cap_move_done(chan);
53863fd71a0aSMat Martineau 	}
53873fd71a0aSMat Martineau 
53883fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
53893fd71a0aSMat Martineau 
53908d5a04a1SMat Martineau 	return 0;
53918d5a04a1SMat Martineau }
53928d5a04a1SMat Martineau 
5393e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
5394de73115aSClaudio Takahasi 					 u16 to_multiplier)
5395de73115aSClaudio Takahasi {
5396de73115aSClaudio Takahasi 	u16 max_latency;
5397de73115aSClaudio Takahasi 
5398de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
5399de73115aSClaudio Takahasi 		return -EINVAL;
5400de73115aSClaudio Takahasi 
5401de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
5402de73115aSClaudio Takahasi 		return -EINVAL;
5403de73115aSClaudio Takahasi 
5404de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
5405de73115aSClaudio Takahasi 		return -EINVAL;
5406de73115aSClaudio Takahasi 
5407de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
5408de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
5409de73115aSClaudio Takahasi 		return -EINVAL;
5410de73115aSClaudio Takahasi 
5411de73115aSClaudio Takahasi 	return 0;
5412de73115aSClaudio Takahasi }
5413de73115aSClaudio Takahasi 
5414de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
54152d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5416203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5417de73115aSClaudio Takahasi {
5418de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5419de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5420de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5421203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
54222ce603ebSClaudio Takahasi 	int err;
5423de73115aSClaudio Takahasi 
5424de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
5425de73115aSClaudio Takahasi 		return -EINVAL;
5426de73115aSClaudio Takahasi 
5427de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5428de73115aSClaudio Takahasi 		return -EPROTO;
5429de73115aSClaudio Takahasi 
5430de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5431de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5432de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5433de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5434de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5435de73115aSClaudio Takahasi 
5436de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5437de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5438de73115aSClaudio Takahasi 
5439de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
54402ce603ebSClaudio Takahasi 
54412ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
54422ce603ebSClaudio Takahasi 	if (err)
5443ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5444de73115aSClaudio Takahasi 	else
5445ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5446de73115aSClaudio Takahasi 
5447de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5448de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5449de73115aSClaudio Takahasi 
54502ce603ebSClaudio Takahasi 	if (!err)
54512ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
54522ce603ebSClaudio Takahasi 
5453de73115aSClaudio Takahasi 	return 0;
5454de73115aSClaudio Takahasi }
5455de73115aSClaudio Takahasi 
5456f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5457f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5458f1496deeSJohan Hedberg 				u8 *data)
5459f1496deeSJohan Hedberg {
5460f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
5461f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5462f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
5463f1496deeSJohan Hedberg 	int err;
5464f1496deeSJohan Hedberg 
5465f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5466f1496deeSJohan Hedberg 		return -EPROTO;
5467f1496deeSJohan Hedberg 
5468f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5469f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5470f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5471f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5472f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5473f1496deeSJohan Hedberg 
5474f1496deeSJohan Hedberg 	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
5475f1496deeSJohan Hedberg 		return -EPROTO;
5476f1496deeSJohan Hedberg 
5477f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5478f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5479f1496deeSJohan Hedberg 
5480f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5481f1496deeSJohan Hedberg 
5482f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5483f1496deeSJohan Hedberg 	if (!chan) {
5484f1496deeSJohan Hedberg 		err = -EBADSLT;
5485f1496deeSJohan Hedberg 		goto unlock;
5486f1496deeSJohan Hedberg 	}
5487f1496deeSJohan Hedberg 
5488f1496deeSJohan Hedberg 	err = 0;
5489f1496deeSJohan Hedberg 
5490f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5491f1496deeSJohan Hedberg 
5492f1496deeSJohan Hedberg 	switch (result) {
5493f1496deeSJohan Hedberg 	case L2CAP_CR_SUCCESS:
5494f1496deeSJohan Hedberg 		chan->ident = 0;
5495f1496deeSJohan Hedberg 		chan->dcid = dcid;
5496f1496deeSJohan Hedberg 		chan->omtu = mtu;
5497f1496deeSJohan Hedberg 		chan->remote_mps = mps;
54980cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5499f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5500f1496deeSJohan Hedberg 		break;
5501f1496deeSJohan Hedberg 
5502f1496deeSJohan Hedberg 	default:
5503f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5504f1496deeSJohan Hedberg 		break;
5505f1496deeSJohan Hedberg 	}
5506f1496deeSJohan Hedberg 
5507f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5508f1496deeSJohan Hedberg 
5509f1496deeSJohan Hedberg unlock:
5510f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5511f1496deeSJohan Hedberg 
5512f1496deeSJohan Hedberg 	return err;
5513f1496deeSJohan Hedberg }
5514f1496deeSJohan Hedberg 
55153300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
55162d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
55172d792818SGustavo Padovan 				      u8 *data)
55183300d9a9SClaudio Takahasi {
55193300d9a9SClaudio Takahasi 	int err = 0;
55203300d9a9SClaudio Takahasi 
55213300d9a9SClaudio Takahasi 	switch (cmd->code) {
55223300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5523cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
55243300d9a9SClaudio Takahasi 		break;
55253300d9a9SClaudio Takahasi 
55263300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5527cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
55283300d9a9SClaudio Takahasi 		break;
55293300d9a9SClaudio Takahasi 
55303300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5531f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
55329245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
55333300d9a9SClaudio Takahasi 		break;
55343300d9a9SClaudio Takahasi 
55353300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
55363300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
55373300d9a9SClaudio Takahasi 		break;
55383300d9a9SClaudio Takahasi 
55393300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
55409245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
55413300d9a9SClaudio Takahasi 		break;
55423300d9a9SClaudio Takahasi 
55433300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5544cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
55453300d9a9SClaudio Takahasi 		break;
55463300d9a9SClaudio Takahasi 
55473300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
55489245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
55493300d9a9SClaudio Takahasi 		break;
55503300d9a9SClaudio Takahasi 
55513300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
55523300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
55533300d9a9SClaudio Takahasi 		break;
55543300d9a9SClaudio Takahasi 
55553300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
55563300d9a9SClaudio Takahasi 		break;
55573300d9a9SClaudio Takahasi 
55583300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5559cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
55603300d9a9SClaudio Takahasi 		break;
55613300d9a9SClaudio Takahasi 
55623300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
55639245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
55643300d9a9SClaudio Takahasi 		break;
55653300d9a9SClaudio Takahasi 
5566f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5567f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5568f94ff6ffSMat Martineau 		break;
5569f94ff6ffSMat Martineau 
55708d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
55718d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
55728d5a04a1SMat Martineau 		break;
55738d5a04a1SMat Martineau 
55748d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
55759245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
55768d5a04a1SMat Martineau 		break;
55778d5a04a1SMat Martineau 
55788d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
55798d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
55808d5a04a1SMat Martineau 		break;
55818d5a04a1SMat Martineau 
55828d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
55839245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
55848d5a04a1SMat Martineau 		break;
55858d5a04a1SMat Martineau 
55863300d9a9SClaudio Takahasi 	default:
55873300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
55883300d9a9SClaudio Takahasi 		err = -EINVAL;
55893300d9a9SClaudio Takahasi 		break;
55903300d9a9SClaudio Takahasi 	}
55913300d9a9SClaudio Takahasi 
55923300d9a9SClaudio Takahasi 	return err;
55933300d9a9SClaudio Takahasi }
55943300d9a9SClaudio Takahasi 
559527e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
559627e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
559727e2d4c8SJohan Hedberg 				u8 *data)
559827e2d4c8SJohan Hedberg {
559927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
560027e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
560127e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
56020cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
560327e2d4c8SJohan Hedberg 	__le16 psm;
560427e2d4c8SJohan Hedberg 	u8 result;
560527e2d4c8SJohan Hedberg 
560627e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
560727e2d4c8SJohan Hedberg 		return -EPROTO;
560827e2d4c8SJohan Hedberg 
560927e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
561027e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
561127e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
561227e2d4c8SJohan Hedberg 	psm  = req->psm;
561327e2d4c8SJohan Hedberg 	dcid = 0;
56140cd75f7eSJohan Hedberg 	credits = 0;
561527e2d4c8SJohan Hedberg 
561627e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
561727e2d4c8SJohan Hedberg 		return -EPROTO;
561827e2d4c8SJohan Hedberg 
561927e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
562027e2d4c8SJohan Hedberg 	       scid, mtu, mps);
562127e2d4c8SJohan Hedberg 
562227e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
562327e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
562427e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
562527e2d4c8SJohan Hedberg 	if (!pchan) {
562627e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
562727e2d4c8SJohan Hedberg 		chan = NULL;
562827e2d4c8SJohan Hedberg 		goto response;
562927e2d4c8SJohan Hedberg 	}
563027e2d4c8SJohan Hedberg 
563127e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
563227e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
563327e2d4c8SJohan Hedberg 
563427e2d4c8SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
563527e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHENTICATION;
563627e2d4c8SJohan Hedberg 		chan = NULL;
563727e2d4c8SJohan Hedberg 		goto response_unlock;
563827e2d4c8SJohan Hedberg 	}
563927e2d4c8SJohan Hedberg 
564027e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
564127e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
564227e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
564327e2d4c8SJohan Hedberg 		chan = NULL;
564427e2d4c8SJohan Hedberg 		goto response_unlock;
564527e2d4c8SJohan Hedberg 	}
564627e2d4c8SJohan Hedberg 
564727e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
564827e2d4c8SJohan Hedberg 	if (!chan) {
564927e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
565027e2d4c8SJohan Hedberg 		goto response_unlock;
565127e2d4c8SJohan Hedberg 	}
565227e2d4c8SJohan Hedberg 
56530ce43ce6SJohan Hedberg 	l2cap_le_flowctl_init(chan);
56540ce43ce6SJohan Hedberg 
565527e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
565627e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
565727e2d4c8SJohan Hedberg 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
565827e2d4c8SJohan Hedberg 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
565927e2d4c8SJohan Hedberg 	chan->psm  = psm;
566027e2d4c8SJohan Hedberg 	chan->dcid = scid;
566127e2d4c8SJohan Hedberg 	chan->omtu = mtu;
566227e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
56630cd75f7eSJohan Hedberg 	chan->tx_credits = __le16_to_cpu(req->credits);
566427e2d4c8SJohan Hedberg 
566527e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
566627e2d4c8SJohan Hedberg 	dcid = chan->scid;
56670cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
566827e2d4c8SJohan Hedberg 
566927e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
567027e2d4c8SJohan Hedberg 
567127e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
567227e2d4c8SJohan Hedberg 
567327e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
567427e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
567527e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
567627e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
567727e2d4c8SJohan Hedberg 	} else {
567827e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
567927e2d4c8SJohan Hedberg 		result = L2CAP_CR_SUCCESS;
568027e2d4c8SJohan Hedberg 	}
568127e2d4c8SJohan Hedberg 
568227e2d4c8SJohan Hedberg response_unlock:
568327e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
568427e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
568527e2d4c8SJohan Hedberg 
568627e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
568727e2d4c8SJohan Hedberg 		return 0;
568827e2d4c8SJohan Hedberg 
568927e2d4c8SJohan Hedberg response:
569027e2d4c8SJohan Hedberg 	if (chan) {
569127e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
56923916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
569327e2d4c8SJohan Hedberg 	} else {
569427e2d4c8SJohan Hedberg 		rsp.mtu = 0;
569527e2d4c8SJohan Hedberg 		rsp.mps = 0;
569627e2d4c8SJohan Hedberg 	}
569727e2d4c8SJohan Hedberg 
569827e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
56990cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
570027e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
570127e2d4c8SJohan Hedberg 
570227e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
570327e2d4c8SJohan Hedberg 
570427e2d4c8SJohan Hedberg 	return 0;
570527e2d4c8SJohan Hedberg }
570627e2d4c8SJohan Hedberg 
5707fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5708fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5709fad5fc89SJohan Hedberg 				   u8 *data)
5710fad5fc89SJohan Hedberg {
5711fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5712fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
5713fad5fc89SJohan Hedberg 	u16 cid, credits;
5714fad5fc89SJohan Hedberg 
5715fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5716fad5fc89SJohan Hedberg 		return -EPROTO;
5717fad5fc89SJohan Hedberg 
5718fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5719fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5720fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5721fad5fc89SJohan Hedberg 
5722fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5723fad5fc89SJohan Hedberg 
5724fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5725fad5fc89SJohan Hedberg 	if (!chan)
5726fad5fc89SJohan Hedberg 		return -EBADSLT;
5727fad5fc89SJohan Hedberg 
5728fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5729fad5fc89SJohan Hedberg 
5730fad5fc89SJohan Hedberg 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
5731fad5fc89SJohan Hedberg 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
5732fad5fc89SJohan Hedberg 		chan->tx_credits--;
5733fad5fc89SJohan Hedberg 	}
5734fad5fc89SJohan Hedberg 
5735fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5736fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5737fad5fc89SJohan Hedberg 
5738fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5739fad5fc89SJohan Hedberg 
5740fad5fc89SJohan Hedberg 	return 0;
5741fad5fc89SJohan Hedberg }
5742fad5fc89SJohan Hedberg 
57433300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5744203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5745203e639eSJohan Hedberg 				   u8 *data)
57463300d9a9SClaudio Takahasi {
5747b5ecba64SJohan Hedberg 	int err = 0;
5748b5ecba64SJohan Hedberg 
57493af8ace6SJohan Hedberg 	if (!enable_lecoc) {
57503af8ace6SJohan Hedberg 		switch (cmd->code) {
57513af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_REQ:
57523af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_RSP:
57533af8ace6SJohan Hedberg 		case L2CAP_LE_CREDITS:
57543af8ace6SJohan Hedberg 		case L2CAP_DISCONN_REQ:
57553af8ace6SJohan Hedberg 		case L2CAP_DISCONN_RSP:
57563af8ace6SJohan Hedberg 			return -EINVAL;
57573af8ace6SJohan Hedberg 		}
57583af8ace6SJohan Hedberg 	}
57593af8ace6SJohan Hedberg 
57603300d9a9SClaudio Takahasi 	switch (cmd->code) {
57613300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5762b5ecba64SJohan Hedberg 		break;
57633300d9a9SClaudio Takahasi 
57643300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5765b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5766b5ecba64SJohan Hedberg 		break;
57673300d9a9SClaudio Takahasi 
57683300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5769b5ecba64SJohan Hedberg 		break;
57703300d9a9SClaudio Takahasi 
5771f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5772f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5773b5ecba64SJohan Hedberg 		break;
5774f1496deeSJohan Hedberg 
577527e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5776b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5777b5ecba64SJohan Hedberg 		break;
577827e2d4c8SJohan Hedberg 
5779fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5780fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5781fad5fc89SJohan Hedberg 		break;
5782fad5fc89SJohan Hedberg 
57833defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5784b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5785b5ecba64SJohan Hedberg 		break;
57863defe01aSJohan Hedberg 
57873defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
57883defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5789b5ecba64SJohan Hedberg 		break;
57903defe01aSJohan Hedberg 
57913300d9a9SClaudio Takahasi 	default:
57923300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5793b5ecba64SJohan Hedberg 		err = -EINVAL;
5794b5ecba64SJohan Hedberg 		break;
57953300d9a9SClaudio Takahasi 	}
5796b5ecba64SJohan Hedberg 
5797b5ecba64SJohan Hedberg 	return err;
57983300d9a9SClaudio Takahasi }
57993300d9a9SClaudio Takahasi 
5800c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5801c5623556SJohan Hedberg 					struct sk_buff *skb)
5802c5623556SJohan Hedberg {
580369c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
58044f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
58054f3e219dSMarcel Holtmann 	u16 len;
5806c5623556SJohan Hedberg 	int err;
5807c5623556SJohan Hedberg 
580869c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
58093b166295SMarcel Holtmann 		goto drop;
581069c4e4e8SJohan Hedberg 
58114f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
58124f3e219dSMarcel Holtmann 		goto drop;
5813c5623556SJohan Hedberg 
58144f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
58154f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5816c5623556SJohan Hedberg 
58174f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5818c5623556SJohan Hedberg 
58194f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
58204f3e219dSMarcel Holtmann 
58214f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5822c5623556SJohan Hedberg 		BT_DBG("corrupted command");
58234f3e219dSMarcel Holtmann 		goto drop;
5824c5623556SJohan Hedberg 	}
5825c5623556SJohan Hedberg 
5826203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5827c5623556SJohan Hedberg 	if (err) {
5828c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5829c5623556SJohan Hedberg 
5830c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5831c5623556SJohan Hedberg 
5832a521149aSJohan Hedberg 		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58334f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5834c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5835c5623556SJohan Hedberg 	}
5836c5623556SJohan Hedberg 
58373b166295SMarcel Holtmann drop:
5838c5623556SJohan Hedberg 	kfree_skb(skb);
5839c5623556SJohan Hedberg }
5840c5623556SJohan Hedberg 
58413300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
58423300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
58430a708f8fSGustavo F. Padovan {
584469c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
58450a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
58460a708f8fSGustavo F. Padovan 	int len = skb->len;
58470a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
58483300d9a9SClaudio Takahasi 	int err;
58490a708f8fSGustavo F. Padovan 
58500a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
58510a708f8fSGustavo F. Padovan 
585269c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
58533b166295SMarcel Holtmann 		goto drop;
585469c4e4e8SJohan Hedberg 
58550a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
58560a708f8fSGustavo F. Padovan 		u16 cmd_len;
58570a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
58580a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
58590a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
58600a708f8fSGustavo F. Padovan 
58610a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
58620a708f8fSGustavo F. Padovan 
58632d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
58642d792818SGustavo Padovan 		       cmd.ident);
58650a708f8fSGustavo F. Padovan 
58660a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
58670a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
58680a708f8fSGustavo F. Padovan 			break;
58690a708f8fSGustavo F. Padovan 		}
58700a708f8fSGustavo F. Padovan 
58713300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
58720a708f8fSGustavo F. Padovan 		if (err) {
5873e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
58742c6d1a2eSGustavo F. Padovan 
58752c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
58760a708f8fSGustavo F. Padovan 
5877a521149aSJohan Hedberg 			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58782d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
58792d792818SGustavo Padovan 				       sizeof(rej), &rej);
58800a708f8fSGustavo F. Padovan 		}
58810a708f8fSGustavo F. Padovan 
58820a708f8fSGustavo F. Padovan 		data += cmd_len;
58830a708f8fSGustavo F. Padovan 		len  -= cmd_len;
58840a708f8fSGustavo F. Padovan 	}
58850a708f8fSGustavo F. Padovan 
58863b166295SMarcel Holtmann drop:
58870a708f8fSGustavo F. Padovan 	kfree_skb(skb);
58880a708f8fSGustavo F. Padovan }
58890a708f8fSGustavo F. Padovan 
589047d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
58910a708f8fSGustavo F. Padovan {
58920a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5893e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5894e4ca6d98SAndrei Emeltchenko 
5895e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5896e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5897e4ca6d98SAndrei Emeltchenko 	else
5898e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
58990a708f8fSGustavo F. Padovan 
590047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
590103a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
59020a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
59030a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
59040a708f8fSGustavo F. Padovan 
59050a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
59060a708f8fSGustavo F. Padovan 			return -EBADMSG;
59070a708f8fSGustavo F. Padovan 	}
59080a708f8fSGustavo F. Padovan 	return 0;
59090a708f8fSGustavo F. Padovan }
59100a708f8fSGustavo F. Padovan 
59116ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
59120a708f8fSGustavo F. Padovan {
5913e31f7633SMat Martineau 	struct l2cap_ctrl control;
59140a708f8fSGustavo F. Padovan 
5915e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
59160a708f8fSGustavo F. Padovan 
5917e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5918e31f7633SMat Martineau 	control.sframe = 1;
5919e31f7633SMat Martineau 	control.final = 1;
5920e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5921e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
59220a708f8fSGustavo F. Padovan 
5923e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5924e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5925e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59260a708f8fSGustavo F. Padovan 	}
59270a708f8fSGustavo F. Padovan 
5928e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5929e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5930e31f7633SMat Martineau 		__set_retrans_timer(chan);
59310a708f8fSGustavo F. Padovan 
5932e31f7633SMat Martineau 	/* Send pending iframes */
5933525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
59340a708f8fSGustavo F. Padovan 
5935e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5936e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5937e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5938e31f7633SMat Martineau 		 * send it now.
5939e31f7633SMat Martineau 		 */
5940e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5941e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59420a708f8fSGustavo F. Padovan 	}
59430a708f8fSGustavo F. Padovan }
59440a708f8fSGustavo F. Padovan 
59452d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
59462d792818SGustavo Padovan 			    struct sk_buff **last_frag)
59470a708f8fSGustavo F. Padovan {
594884084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
594984084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
595084084a31SMat Martineau 	 */
595184084a31SMat Martineau 	if (!skb_has_frag_list(skb))
595284084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
595384084a31SMat Martineau 
595484084a31SMat Martineau 	new_frag->next = NULL;
595584084a31SMat Martineau 
595684084a31SMat Martineau 	(*last_frag)->next = new_frag;
595784084a31SMat Martineau 	*last_frag = new_frag;
595884084a31SMat Martineau 
595984084a31SMat Martineau 	skb->len += new_frag->len;
596084084a31SMat Martineau 	skb->data_len += new_frag->len;
596184084a31SMat Martineau 	skb->truesize += new_frag->truesize;
596284084a31SMat Martineau }
596384084a31SMat Martineau 
59644b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
59654b51dae9SMat Martineau 				struct l2cap_ctrl *control)
596684084a31SMat Martineau {
596784084a31SMat Martineau 	int err = -EINVAL;
59680a708f8fSGustavo F. Padovan 
59694b51dae9SMat Martineau 	switch (control->sar) {
59707e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
597184084a31SMat Martineau 		if (chan->sdu)
597284084a31SMat Martineau 			break;
59730a708f8fSGustavo F. Padovan 
597480b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
597584084a31SMat Martineau 		break;
59760a708f8fSGustavo F. Padovan 
59777e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
597884084a31SMat Martineau 		if (chan->sdu)
597984084a31SMat Martineau 			break;
59800a708f8fSGustavo F. Padovan 
59816f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
598203a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
59830a708f8fSGustavo F. Padovan 
598484084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
598584084a31SMat Martineau 			err = -EMSGSIZE;
598684084a31SMat Martineau 			break;
598784084a31SMat Martineau 		}
59880a708f8fSGustavo F. Padovan 
598984084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
599084084a31SMat Martineau 			break;
599184084a31SMat Martineau 
599284084a31SMat Martineau 		chan->sdu = skb;
599384084a31SMat Martineau 		chan->sdu_last_frag = skb;
599484084a31SMat Martineau 
599584084a31SMat Martineau 		skb = NULL;
599684084a31SMat Martineau 		err = 0;
59970a708f8fSGustavo F. Padovan 		break;
59980a708f8fSGustavo F. Padovan 
59997e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
60006f61fd47SGustavo F. Padovan 		if (!chan->sdu)
600184084a31SMat Martineau 			break;
60020a708f8fSGustavo F. Padovan 
600384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
600484084a31SMat Martineau 				&chan->sdu_last_frag);
600584084a31SMat Martineau 		skb = NULL;
60060a708f8fSGustavo F. Padovan 
600784084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
600884084a31SMat Martineau 			break;
60090a708f8fSGustavo F. Padovan 
601084084a31SMat Martineau 		err = 0;
60110a708f8fSGustavo F. Padovan 		break;
60120a708f8fSGustavo F. Padovan 
60137e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
60146f61fd47SGustavo F. Padovan 		if (!chan->sdu)
601584084a31SMat Martineau 			break;
60160a708f8fSGustavo F. Padovan 
601784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
601884084a31SMat Martineau 				&chan->sdu_last_frag);
601984084a31SMat Martineau 		skb = NULL;
60200a708f8fSGustavo F. Padovan 
602184084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
602284084a31SMat Martineau 			break;
60230a708f8fSGustavo F. Padovan 
602480b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
60250a708f8fSGustavo F. Padovan 
602684084a31SMat Martineau 		if (!err) {
602784084a31SMat Martineau 			/* Reassembly complete */
602884084a31SMat Martineau 			chan->sdu = NULL;
602984084a31SMat Martineau 			chan->sdu_last_frag = NULL;
603084084a31SMat Martineau 			chan->sdu_len = 0;
60310a708f8fSGustavo F. Padovan 		}
60320a708f8fSGustavo F. Padovan 		break;
60330a708f8fSGustavo F. Padovan 	}
60340a708f8fSGustavo F. Padovan 
603584084a31SMat Martineau 	if (err) {
60360a708f8fSGustavo F. Padovan 		kfree_skb(skb);
60376f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
60386f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
603984084a31SMat Martineau 		chan->sdu_last_frag = NULL;
604084084a31SMat Martineau 		chan->sdu_len = 0;
604184084a31SMat Martineau 	}
60420a708f8fSGustavo F. Padovan 
604384084a31SMat Martineau 	return err;
60440a708f8fSGustavo F. Padovan }
60450a708f8fSGustavo F. Padovan 
604632b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
604732b32735SMat Martineau {
604832b32735SMat Martineau 	/* Placeholder */
604932b32735SMat Martineau 	return 0;
605032b32735SMat Martineau }
605132b32735SMat Martineau 
6052e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
60530a708f8fSGustavo F. Padovan {
605461aa4f5bSMat Martineau 	u8 event;
605561aa4f5bSMat Martineau 
605661aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
605761aa4f5bSMat Martineau 		return;
605861aa4f5bSMat Martineau 
605961aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6060401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
60610a708f8fSGustavo F. Padovan }
60620a708f8fSGustavo F. Padovan 
6063d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6064d2a7ac5dSMat Martineau {
606563838725SMat Martineau 	int err = 0;
606663838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
606763838725SMat Martineau 	 * until a gap is encountered.
606863838725SMat Martineau 	 */
606963838725SMat Martineau 
607063838725SMat Martineau 	BT_DBG("chan %p", chan);
607163838725SMat Martineau 
607263838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
607363838725SMat Martineau 		struct sk_buff *skb;
607463838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
607563838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
607663838725SMat Martineau 
607763838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
607863838725SMat Martineau 
607963838725SMat Martineau 		if (!skb)
608063838725SMat Martineau 			break;
608163838725SMat Martineau 
608263838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
608363838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
608463838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
608563838725SMat Martineau 		if (err)
608663838725SMat Martineau 			break;
608763838725SMat Martineau 	}
608863838725SMat Martineau 
608963838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
609063838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
609163838725SMat Martineau 		l2cap_send_ack(chan);
609263838725SMat Martineau 	}
609363838725SMat Martineau 
609463838725SMat Martineau 	return err;
6095d2a7ac5dSMat Martineau }
6096d2a7ac5dSMat Martineau 
6097d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6098d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6099d2a7ac5dSMat Martineau {
6100f80842a8SMat Martineau 	struct sk_buff *skb;
6101f80842a8SMat Martineau 
6102f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6103f80842a8SMat Martineau 
6104f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6105f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61065e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6107f80842a8SMat Martineau 		return;
6108f80842a8SMat Martineau 	}
6109f80842a8SMat Martineau 
6110f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6111f80842a8SMat Martineau 
6112f80842a8SMat Martineau 	if (skb == NULL) {
6113f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6114f80842a8SMat Martineau 		       control->reqseq);
6115f80842a8SMat Martineau 		return;
6116f80842a8SMat Martineau 	}
6117f80842a8SMat Martineau 
6118f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
6119f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61205e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6121f80842a8SMat Martineau 		return;
6122f80842a8SMat Martineau 	}
6123f80842a8SMat Martineau 
6124f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6125f80842a8SMat Martineau 
6126f80842a8SMat Martineau 	if (control->poll) {
6127f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6128f80842a8SMat Martineau 
6129f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6130f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6131f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6132f80842a8SMat Martineau 
6133f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6134f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6135f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6136f80842a8SMat Martineau 		}
6137f80842a8SMat Martineau 	} else {
6138f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6139f80842a8SMat Martineau 
6140f80842a8SMat Martineau 		if (control->final) {
6141f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6142f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6143f80842a8SMat Martineau 						&chan->conn_state))
6144f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6145f80842a8SMat Martineau 		} else {
6146f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6147f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6148f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6149f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6150f80842a8SMat Martineau 			}
6151f80842a8SMat Martineau 		}
6152f80842a8SMat Martineau 	}
6153d2a7ac5dSMat Martineau }
6154d2a7ac5dSMat Martineau 
6155d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6156d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6157d2a7ac5dSMat Martineau {
6158fcd289dfSMat Martineau 	struct sk_buff *skb;
6159fcd289dfSMat Martineau 
6160fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6161fcd289dfSMat Martineau 
6162fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6163fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61645e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6165fcd289dfSMat Martineau 		return;
6166fcd289dfSMat Martineau 	}
6167fcd289dfSMat Martineau 
6168fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6169fcd289dfSMat Martineau 
6170fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6171fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
6172fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61735e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6174fcd289dfSMat Martineau 		return;
6175fcd289dfSMat Martineau 	}
6176fcd289dfSMat Martineau 
6177fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6178fcd289dfSMat Martineau 
6179fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6180fcd289dfSMat Martineau 
6181fcd289dfSMat Martineau 	if (control->final) {
6182fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6183fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6184fcd289dfSMat Martineau 	} else {
6185fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6186fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6187fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6188fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6189fcd289dfSMat Martineau 	}
6190d2a7ac5dSMat Martineau }
6191d2a7ac5dSMat Martineau 
61924b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
61934b51dae9SMat Martineau {
61944b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
61954b51dae9SMat Martineau 
61964b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
61974b51dae9SMat Martineau 	       chan->expected_tx_seq);
61984b51dae9SMat Martineau 
61994b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
62004b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
62014b51dae9SMat Martineau 		    chan->tx_win) {
62024b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
62034b51dae9SMat Martineau 			 * invalid packets.
62044b51dae9SMat Martineau 			 */
62054b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62064b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
62074b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
62084b51dae9SMat Martineau 			} else {
62094b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
62104b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
62114b51dae9SMat Martineau 			}
62124b51dae9SMat Martineau 		}
62134b51dae9SMat Martineau 
62144b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
62154b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
62164b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
62174b51dae9SMat Martineau 		}
62184b51dae9SMat Martineau 
62194b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
62204b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
62214b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
62224b51dae9SMat Martineau 		}
62234b51dae9SMat Martineau 
62244b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
62254b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
62264b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
62274b51dae9SMat Martineau 		}
62284b51dae9SMat Martineau 	}
62294b51dae9SMat Martineau 
62304b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
62314b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
62324b51dae9SMat Martineau 		    chan->tx_win) {
62334b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62344b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62354b51dae9SMat Martineau 		} else {
62364b51dae9SMat Martineau 			BT_DBG("Expected");
62374b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
62384b51dae9SMat Martineau 		}
62394b51dae9SMat Martineau 	}
62404b51dae9SMat Martineau 
62414b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
62422d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
62434b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
62444b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
62454b51dae9SMat Martineau 	}
62464b51dae9SMat Martineau 
62474b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
62484b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
62494b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
62504b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
62514b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
62524b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
62534b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
62544b51dae9SMat Martineau 		 * request.
62554b51dae9SMat Martineau 		 *
62564b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
62574b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
62584b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
62594b51dae9SMat Martineau 		 *
62604b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
62614b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
62624b51dae9SMat Martineau 		 * causes a disconnect.
62634b51dae9SMat Martineau 		 */
62644b51dae9SMat Martineau 
62654b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62664b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
62674b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
62684b51dae9SMat Martineau 		} else {
62694b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62704b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62714b51dae9SMat Martineau 		}
62724b51dae9SMat Martineau 	} else {
62734b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
62744b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
62754b51dae9SMat Martineau 	}
62764b51dae9SMat Martineau }
62774b51dae9SMat Martineau 
6278d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6279d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6280d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6281d2a7ac5dSMat Martineau {
6282d2a7ac5dSMat Martineau 	int err = 0;
6283941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6284d2a7ac5dSMat Martineau 
6285d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6286d2a7ac5dSMat Martineau 	       event);
6287d2a7ac5dSMat Martineau 
6288d2a7ac5dSMat Martineau 	switch (event) {
6289d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6290d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6291d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6292d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6293d2a7ac5dSMat Martineau 
6294d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6295d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6296d2a7ac5dSMat Martineau 				       control->txseq);
6297d2a7ac5dSMat Martineau 				break;
6298d2a7ac5dSMat Martineau 			}
6299d2a7ac5dSMat Martineau 
6300d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6301d2a7ac5dSMat Martineau 							   control->txseq);
6302d2a7ac5dSMat Martineau 
6303d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6304941247f9SPeter Senna Tschudin 			skb_in_use = true;
6305d2a7ac5dSMat Martineau 
6306d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6307d2a7ac5dSMat Martineau 			if (err)
6308d2a7ac5dSMat Martineau 				break;
6309d2a7ac5dSMat Martineau 
6310d2a7ac5dSMat Martineau 			if (control->final) {
6311d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6312d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6313d2a7ac5dSMat Martineau 					control->final = 0;
6314d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6315d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6316d2a7ac5dSMat Martineau 				}
6317d2a7ac5dSMat Martineau 			}
6318d2a7ac5dSMat Martineau 
6319d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6320d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6321d2a7ac5dSMat Martineau 			break;
6322d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6323d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6324d2a7ac5dSMat Martineau 
6325d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6326d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6327d2a7ac5dSMat Martineau 			 * when local busy is exited.
6328d2a7ac5dSMat Martineau 			 */
6329d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6330d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6331d2a7ac5dSMat Martineau 				       control->txseq);
6332d2a7ac5dSMat Martineau 				break;
6333d2a7ac5dSMat Martineau 			}
6334d2a7ac5dSMat Martineau 
6335d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6336d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6337d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6338d2a7ac5dSMat Martineau 			 */
6339d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6340941247f9SPeter Senna Tschudin 			skb_in_use = true;
6341d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6342d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6343d2a7ac5dSMat Martineau 
6344d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6345d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6346d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6347d2a7ac5dSMat Martineau 
6348d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6349d2a7ac5dSMat Martineau 			break;
6350d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6351d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6352d2a7ac5dSMat Martineau 			break;
6353d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6354d2a7ac5dSMat Martineau 			break;
6355d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6356d2a7ac5dSMat Martineau 		default:
63575e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6358d2a7ac5dSMat Martineau 			break;
6359d2a7ac5dSMat Martineau 		}
6360d2a7ac5dSMat Martineau 		break;
6361d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6362d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6363d2a7ac5dSMat Martineau 		if (control->final) {
6364d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6365d2a7ac5dSMat Martineau 
6366e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6367e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6368d2a7ac5dSMat Martineau 				control->final = 0;
6369d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6370d2a7ac5dSMat Martineau 			}
6371d2a7ac5dSMat Martineau 
6372d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6373d2a7ac5dSMat Martineau 		} else if (control->poll) {
6374d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6375d2a7ac5dSMat Martineau 		} else {
6376d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6377d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6378d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6379d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6380d2a7ac5dSMat Martineau 
6381d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6382d2a7ac5dSMat Martineau 		}
6383d2a7ac5dSMat Martineau 		break;
6384d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6385d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6386d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6387d2a7ac5dSMat Martineau 		if (control && control->poll) {
6388d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6389d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6390d2a7ac5dSMat Martineau 		}
6391d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6392d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6393d2a7ac5dSMat Martineau 		break;
6394d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6395d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6396d2a7ac5dSMat Martineau 		break;
6397d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6398d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6399d2a7ac5dSMat Martineau 		break;
6400d2a7ac5dSMat Martineau 	default:
6401d2a7ac5dSMat Martineau 		break;
6402d2a7ac5dSMat Martineau 	}
6403d2a7ac5dSMat Martineau 
6404d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6405d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6406d2a7ac5dSMat Martineau 		kfree_skb(skb);
6407d2a7ac5dSMat Martineau 	}
6408d2a7ac5dSMat Martineau 
6409d2a7ac5dSMat Martineau 	return err;
6410d2a7ac5dSMat Martineau }
6411d2a7ac5dSMat Martineau 
6412d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6413d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6414d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6415d2a7ac5dSMat Martineau {
6416d2a7ac5dSMat Martineau 	int err = 0;
6417d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6418941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6419d2a7ac5dSMat Martineau 
6420d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6421d2a7ac5dSMat Martineau 	       event);
6422d2a7ac5dSMat Martineau 
6423d2a7ac5dSMat Martineau 	switch (event) {
6424d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6425d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6426d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6427d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6428d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6429d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6430941247f9SPeter Senna Tschudin 			skb_in_use = true;
6431d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6432d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6433d2a7ac5dSMat Martineau 
6434d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6435d2a7ac5dSMat Martineau 			break;
6436d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6437d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6438d2a7ac5dSMat Martineau 
6439d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6440d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6441941247f9SPeter Senna Tschudin 			skb_in_use = true;
6442d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6443d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6444d2a7ac5dSMat Martineau 
6445d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6446d2a7ac5dSMat Martineau 			if (err)
6447d2a7ac5dSMat Martineau 				break;
6448d2a7ac5dSMat Martineau 
6449d2a7ac5dSMat Martineau 			break;
6450d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6451d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6452d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6453d2a7ac5dSMat Martineau 			 * the missing frames.
6454d2a7ac5dSMat Martineau 			 */
6455d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6456941247f9SPeter Senna Tschudin 			skb_in_use = true;
6457d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6458d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6459d2a7ac5dSMat Martineau 
6460d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6461d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6462d2a7ac5dSMat Martineau 			break;
6463d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6464d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6465d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6466d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6467d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6468d2a7ac5dSMat Martineau 			 */
6469d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6470941247f9SPeter Senna Tschudin 			skb_in_use = true;
6471d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6472d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6473d2a7ac5dSMat Martineau 
6474d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6475d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6476d2a7ac5dSMat Martineau 			break;
6477d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6478d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6479d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6480d2a7ac5dSMat Martineau 			break;
6481d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6482d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6483d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6484d2a7ac5dSMat Martineau 			 */
6485d2a7ac5dSMat Martineau 			break;
6486d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6487d2a7ac5dSMat Martineau 			break;
6488d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6489d2a7ac5dSMat Martineau 		default:
64905e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6491d2a7ac5dSMat Martineau 			break;
6492d2a7ac5dSMat Martineau 		}
6493d2a7ac5dSMat Martineau 		break;
6494d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6495d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6496d2a7ac5dSMat Martineau 		if (control->final) {
6497d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6498d2a7ac5dSMat Martineau 
6499d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6500d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6501d2a7ac5dSMat Martineau 				control->final = 0;
6502d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6503d2a7ac5dSMat Martineau 			}
6504d2a7ac5dSMat Martineau 
6505d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6506d2a7ac5dSMat Martineau 		} else if (control->poll) {
6507d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6508d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6509d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6510d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6511d2a7ac5dSMat Martineau 			}
6512d2a7ac5dSMat Martineau 
6513d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6514d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6515d2a7ac5dSMat Martineau 		} else {
6516d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6517d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6518d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6519d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6520d2a7ac5dSMat Martineau 
6521d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6522d2a7ac5dSMat Martineau 		}
6523d2a7ac5dSMat Martineau 		break;
6524d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6525d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6526d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6527d2a7ac5dSMat Martineau 		if (control->poll) {
6528d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6529d2a7ac5dSMat Martineau 		} else {
6530d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6531d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6532d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6533d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6534d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6535d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6536d2a7ac5dSMat Martineau 		}
6537d2a7ac5dSMat Martineau 
6538d2a7ac5dSMat Martineau 		break;
6539d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6540d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6541d2a7ac5dSMat Martineau 		break;
6542d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6543d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6544d2a7ac5dSMat Martineau 		break;
6545d2a7ac5dSMat Martineau 	}
6546d2a7ac5dSMat Martineau 
6547d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6548d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6549d2a7ac5dSMat Martineau 		kfree_skb(skb);
6550d2a7ac5dSMat Martineau 	}
6551d2a7ac5dSMat Martineau 
6552d2a7ac5dSMat Martineau 	return err;
6553d2a7ac5dSMat Martineau }
6554d2a7ac5dSMat Martineau 
655532b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
655632b32735SMat Martineau {
655732b32735SMat Martineau 	BT_DBG("chan %p", chan);
655832b32735SMat Martineau 
655932b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
656032b32735SMat Martineau 
656132b32735SMat Martineau 	if (chan->hs_hcon)
656232b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
656332b32735SMat Martineau 	else
656432b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
656532b32735SMat Martineau 
656632b32735SMat Martineau 	return l2cap_resegment(chan);
656732b32735SMat Martineau }
656832b32735SMat Martineau 
656932b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
657032b32735SMat Martineau 				 struct l2cap_ctrl *control,
657132b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
657232b32735SMat Martineau {
657332b32735SMat Martineau 	int err;
657432b32735SMat Martineau 
657532b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
657632b32735SMat Martineau 	       event);
657732b32735SMat Martineau 
657832b32735SMat Martineau 	if (!control->poll)
657932b32735SMat Martineau 		return -EPROTO;
658032b32735SMat Martineau 
658132b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
658232b32735SMat Martineau 
658332b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
658432b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
658532b32735SMat Martineau 	else
658632b32735SMat Martineau 		chan->tx_send_head = NULL;
658732b32735SMat Martineau 
658832b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
658932b32735SMat Martineau 	 * by the receiver.
659032b32735SMat Martineau 	 */
659132b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
659232b32735SMat Martineau 	chan->unacked_frames = 0;
659332b32735SMat Martineau 
659432b32735SMat Martineau 	err = l2cap_finish_move(chan);
659532b32735SMat Martineau 	if (err)
659632b32735SMat Martineau 		return err;
659732b32735SMat Martineau 
659832b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
659932b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
660032b32735SMat Martineau 
660132b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
660232b32735SMat Martineau 		return -EPROTO;
660332b32735SMat Martineau 
660432b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
660532b32735SMat Martineau }
660632b32735SMat Martineau 
660732b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
660832b32735SMat Martineau 				 struct l2cap_ctrl *control,
660932b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
661032b32735SMat Martineau {
661132b32735SMat Martineau 	int err;
661232b32735SMat Martineau 
661332b32735SMat Martineau 	if (!control->final)
661432b32735SMat Martineau 		return -EPROTO;
661532b32735SMat Martineau 
661632b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
661732b32735SMat Martineau 
661832b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
661932b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
662032b32735SMat Martineau 
662132b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
662232b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
662332b32735SMat Martineau 	else
662432b32735SMat Martineau 		chan->tx_send_head = NULL;
662532b32735SMat Martineau 
662632b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
662732b32735SMat Martineau 	 * by the receiver.
662832b32735SMat Martineau 	 */
662932b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
663032b32735SMat Martineau 	chan->unacked_frames = 0;
663132b32735SMat Martineau 
663232b32735SMat Martineau 	if (chan->hs_hcon)
663332b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
663432b32735SMat Martineau 	else
663532b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
663632b32735SMat Martineau 
663732b32735SMat Martineau 	err = l2cap_resegment(chan);
663832b32735SMat Martineau 
663932b32735SMat Martineau 	if (!err)
664032b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
664132b32735SMat Martineau 
664232b32735SMat Martineau 	return err;
664332b32735SMat Martineau }
664432b32735SMat Martineau 
6645d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6646d2a7ac5dSMat Martineau {
6647d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6648d2a7ac5dSMat Martineau 	u16 unacked;
6649d2a7ac5dSMat Martineau 
6650d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6651d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6652d2a7ac5dSMat Martineau }
6653d2a7ac5dSMat Martineau 
6654cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6655cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
66560a708f8fSGustavo F. Padovan {
6657d2a7ac5dSMat Martineau 	int err = 0;
6658d2a7ac5dSMat Martineau 
6659d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6660d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6661d2a7ac5dSMat Martineau 
6662d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6663d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6664d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6665d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6666d2a7ac5dSMat Martineau 			break;
6667d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6668d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6669d2a7ac5dSMat Martineau 						       event);
6670d2a7ac5dSMat Martineau 			break;
667132b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
667232b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
667332b32735SMat Martineau 			break;
667432b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
667532b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
667632b32735SMat Martineau 			break;
6677d2a7ac5dSMat Martineau 		default:
6678d2a7ac5dSMat Martineau 			/* shut it down */
6679d2a7ac5dSMat Martineau 			break;
6680d2a7ac5dSMat Martineau 		}
6681d2a7ac5dSMat Martineau 	} else {
6682d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6683d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6684d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
66855e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6686d2a7ac5dSMat Martineau 	}
6687d2a7ac5dSMat Martineau 
6688d2a7ac5dSMat Martineau 	return err;
6689cec8ab6eSMat Martineau }
6690cec8ab6eSMat Martineau 
6691cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6692cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6693cec8ab6eSMat Martineau {
66944b51dae9SMat Martineau 	int err = 0;
66954b51dae9SMat Martineau 
66964b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
66974b51dae9SMat Martineau 	       chan->rx_state);
66984b51dae9SMat Martineau 
66994b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
67004b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
67014b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
67024b51dae9SMat Martineau 
67034b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
67044b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
67054b51dae9SMat Martineau 
67064b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
67074b51dae9SMat Martineau 
67084b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
67094b51dae9SMat Martineau 	} else {
67104b51dae9SMat Martineau 		if (chan->sdu) {
67114b51dae9SMat Martineau 			kfree_skb(chan->sdu);
67124b51dae9SMat Martineau 			chan->sdu = NULL;
67134b51dae9SMat Martineau 		}
67144b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
67154b51dae9SMat Martineau 		chan->sdu_len = 0;
67164b51dae9SMat Martineau 
67174b51dae9SMat Martineau 		if (skb) {
67184b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
67194b51dae9SMat Martineau 			kfree_skb(skb);
67204b51dae9SMat Martineau 		}
67214b51dae9SMat Martineau 	}
67224b51dae9SMat Martineau 
67234b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
67244b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
67254b51dae9SMat Martineau 
67264b51dae9SMat Martineau 	return err;
6727cec8ab6eSMat Martineau }
6728cec8ab6eSMat Martineau 
6729cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6730cec8ab6eSMat Martineau {
6731cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
6732cec8ab6eSMat Martineau 	u16 len;
6733cec8ab6eSMat Martineau 	u8 event;
67340a708f8fSGustavo F. Padovan 
6735b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6736b76bbd66SMat Martineau 
67370a708f8fSGustavo F. Padovan 	len = skb->len;
67380a708f8fSGustavo F. Padovan 
67390a708f8fSGustavo F. Padovan 	/*
67400a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
67410a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6742cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
67430a708f8fSGustavo F. Padovan 	 */
674447d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
67450a708f8fSGustavo F. Padovan 		goto drop;
67460a708f8fSGustavo F. Padovan 
6747cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
674803a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
67490a708f8fSGustavo F. Padovan 
675047d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
675103a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
67520a708f8fSGustavo F. Padovan 
675347d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
67545e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
67550a708f8fSGustavo F. Padovan 		goto drop;
67560a708f8fSGustavo F. Padovan 	}
67570a708f8fSGustavo F. Padovan 
6758cec8ab6eSMat Martineau 	if (!control->sframe) {
6759cec8ab6eSMat Martineau 		int err;
67600a708f8fSGustavo F. Padovan 
6761cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6762cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6763cec8ab6eSMat Martineau 		       control->txseq);
6764836be934SAndrei Emeltchenko 
6765cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6766cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6767cec8ab6eSMat Martineau 		 */
6768cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
67690a708f8fSGustavo F. Padovan 			goto drop;
67700a708f8fSGustavo F. Padovan 
6771cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6772cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6773cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
67740a708f8fSGustavo F. Padovan 		} else {
6775cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6776cec8ab6eSMat Martineau 		}
6777cec8ab6eSMat Martineau 
6778cec8ab6eSMat Martineau 		if (err)
67795e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6780cec8ab6eSMat Martineau 	} else {
6781cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6782cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6783cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6784cec8ab6eSMat Martineau 		};
6785cec8ab6eSMat Martineau 
6786cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6787cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6788cec8ab6eSMat Martineau 			goto drop;
6789cec8ab6eSMat Martineau 
6790cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6791cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6792cec8ab6eSMat Martineau 		       control->super);
6793cec8ab6eSMat Martineau 
67940a708f8fSGustavo F. Padovan 		if (len != 0) {
67951bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
67965e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67970a708f8fSGustavo F. Padovan 			goto drop;
67980a708f8fSGustavo F. Padovan 		}
67990a708f8fSGustavo F. Padovan 
6800cec8ab6eSMat Martineau 		/* Validate F and P bits */
6801cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6802cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6803cec8ab6eSMat Martineau 			goto drop;
6804cec8ab6eSMat Martineau 
6805cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6806cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
68075e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
68080a708f8fSGustavo F. Padovan 	}
68090a708f8fSGustavo F. Padovan 
68100a708f8fSGustavo F. Padovan 	return 0;
68110a708f8fSGustavo F. Padovan 
68120a708f8fSGustavo F. Padovan drop:
68130a708f8fSGustavo F. Padovan 	kfree_skb(skb);
68140a708f8fSGustavo F. Padovan 	return 0;
68150a708f8fSGustavo F. Padovan }
68160a708f8fSGustavo F. Padovan 
6817b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6818b1c325c2SJohan Hedberg {
6819b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6820b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6821b1c325c2SJohan Hedberg 	u16 return_credits;
6822b1c325c2SJohan Hedberg 
6823b1c325c2SJohan Hedberg 	/* We return more credits to the sender only after the amount of
6824b1c325c2SJohan Hedberg 	 * credits falls below half of the initial amount.
6825b1c325c2SJohan Hedberg 	 */
6826f15b8ecfSJohan Hedberg 	if (chan->rx_credits >= (le_max_credits + 1) / 2)
6827b1c325c2SJohan Hedberg 		return;
6828b1c325c2SJohan Hedberg 
6829f15b8ecfSJohan Hedberg 	return_credits = le_max_credits - chan->rx_credits;
6830b1c325c2SJohan Hedberg 
6831b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6832b1c325c2SJohan Hedberg 
6833b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6834b1c325c2SJohan Hedberg 
6835b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6836b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6837b1c325c2SJohan Hedberg 
6838b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6839b1c325c2SJohan Hedberg 
6840b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6841b1c325c2SJohan Hedberg }
6842b1c325c2SJohan Hedberg 
6843fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6844fad5fc89SJohan Hedberg {
6845aac23bf6SJohan Hedberg 	int err;
6846fad5fc89SJohan Hedberg 
6847aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6848aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6849fad5fc89SJohan Hedberg 		return -ENOBUFS;
6850aac23bf6SJohan Hedberg 	}
6851aac23bf6SJohan Hedberg 
6852aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6853aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6854aac23bf6SJohan Hedberg 		return -ENOBUFS;
6855aac23bf6SJohan Hedberg 	}
6856fad5fc89SJohan Hedberg 
6857fad5fc89SJohan Hedberg 	chan->rx_credits--;
6858fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6859fad5fc89SJohan Hedberg 
6860fad5fc89SJohan Hedberg 	l2cap_chan_le_send_credits(chan);
6861fad5fc89SJohan Hedberg 
6862aac23bf6SJohan Hedberg 	err = 0;
6863aac23bf6SJohan Hedberg 
6864aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6865aac23bf6SJohan Hedberg 		u16 sdu_len;
6866aac23bf6SJohan Hedberg 
6867aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6868aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6869aac23bf6SJohan Hedberg 
6870aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6871aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6872aac23bf6SJohan Hedberg 
6873aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6874aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6875aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6876aac23bf6SJohan Hedberg 			goto failed;
6877aac23bf6SJohan Hedberg 		}
6878aac23bf6SJohan Hedberg 
6879aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6880aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6881aac23bf6SJohan Hedberg 			err = -EINVAL;
6882aac23bf6SJohan Hedberg 			goto failed;
6883aac23bf6SJohan Hedberg 		}
6884aac23bf6SJohan Hedberg 
6885aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
6886fad5fc89SJohan Hedberg 			return chan->ops->recv(chan, skb);
6887aac23bf6SJohan Hedberg 
6888aac23bf6SJohan Hedberg 		chan->sdu = skb;
6889aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6890aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6891aac23bf6SJohan Hedberg 
6892aac23bf6SJohan Hedberg 		return 0;
6893aac23bf6SJohan Hedberg 	}
6894aac23bf6SJohan Hedberg 
6895aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6896aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6897aac23bf6SJohan Hedberg 
6898aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6899aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6900aac23bf6SJohan Hedberg 		err = -EINVAL;
6901aac23bf6SJohan Hedberg 		goto failed;
6902aac23bf6SJohan Hedberg 	}
6903aac23bf6SJohan Hedberg 
6904aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6905aac23bf6SJohan Hedberg 	skb = NULL;
6906aac23bf6SJohan Hedberg 
6907aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
6908aac23bf6SJohan Hedberg 		err = chan->ops->recv(chan, chan->sdu);
6909aac23bf6SJohan Hedberg 		if (!err) {
6910aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6911aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6912aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6913aac23bf6SJohan Hedberg 		}
6914aac23bf6SJohan Hedberg 	}
6915aac23bf6SJohan Hedberg 
6916aac23bf6SJohan Hedberg failed:
6917aac23bf6SJohan Hedberg 	if (err) {
6918aac23bf6SJohan Hedberg 		kfree_skb(skb);
6919aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6920aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6921aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6922aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6923aac23bf6SJohan Hedberg 	}
6924aac23bf6SJohan Hedberg 
6925aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6926aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6927aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6928aac23bf6SJohan Hedberg 	 */
6929aac23bf6SJohan Hedberg 	return 0;
6930fad5fc89SJohan Hedberg }
6931fad5fc89SJohan Hedberg 
693213ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
693313ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
69340a708f8fSGustavo F. Padovan {
693548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
69360a708f8fSGustavo F. Padovan 
6937baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
693848454079SGustavo F. Padovan 	if (!chan) {
693997e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
694097e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
694197e8e89dSAndrei Emeltchenko 			if (!chan) {
694297e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
694313ca56e0SAndrei Emeltchenko 				return;
694497e8e89dSAndrei Emeltchenko 			}
694597e8e89dSAndrei Emeltchenko 
694697e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
694797e8e89dSAndrei Emeltchenko 		} else {
69480a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
69496be36555SAndrei Emeltchenko 			/* Drop packet and return */
69503379013bSDan Carpenter 			kfree_skb(skb);
695113ca56e0SAndrei Emeltchenko 			return;
69520a708f8fSGustavo F. Padovan 		}
695397e8e89dSAndrei Emeltchenko 	}
69540a708f8fSGustavo F. Padovan 
695549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
69560a708f8fSGustavo F. Padovan 
695789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
69580a708f8fSGustavo F. Padovan 		goto drop;
69590a708f8fSGustavo F. Padovan 
69600c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
696138319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
6962fad5fc89SJohan Hedberg 		if (l2cap_le_data_rcv(chan, skb) < 0)
6963fad5fc89SJohan Hedberg 			goto drop;
6964fad5fc89SJohan Hedberg 
6965fad5fc89SJohan Hedberg 		goto done;
6966fad5fc89SJohan Hedberg 
69670a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
69680a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
69690a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
69700a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
69710a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
69720a708f8fSGustavo F. Padovan 
69730c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
69740a708f8fSGustavo F. Padovan 			goto drop;
69750a708f8fSGustavo F. Padovan 
697680b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
69770a708f8fSGustavo F. Padovan 			goto done;
69780a708f8fSGustavo F. Padovan 		break;
69790a708f8fSGustavo F. Padovan 
69800a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
69810a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6982cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
69830a708f8fSGustavo F. Padovan 		goto done;
69840a708f8fSGustavo F. Padovan 
69850a708f8fSGustavo F. Padovan 	default:
69860c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
69870a708f8fSGustavo F. Padovan 		break;
69880a708f8fSGustavo F. Padovan 	}
69890a708f8fSGustavo F. Padovan 
69900a708f8fSGustavo F. Padovan drop:
69910a708f8fSGustavo F. Padovan 	kfree_skb(skb);
69920a708f8fSGustavo F. Padovan 
69930a708f8fSGustavo F. Padovan done:
69946be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
69950a708f8fSGustavo F. Padovan }
69960a708f8fSGustavo F. Padovan 
699784104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
699884104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
69990a708f8fSGustavo F. Padovan {
7000ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
700123691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
70020a708f8fSGustavo F. Padovan 
7003ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
7004ae4fd2d3SMarcel Holtmann 		goto drop;
7005ae4fd2d3SMarcel Holtmann 
7006bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
7007bf20fd4eSJohan Hedberg 					ACL_LINK);
700823691d75SGustavo F. Padovan 	if (!chan)
70090a708f8fSGustavo F. Padovan 		goto drop;
70100a708f8fSGustavo F. Padovan 
70115b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
70120a708f8fSGustavo F. Padovan 
701389bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
70140a708f8fSGustavo F. Padovan 		goto drop;
70150a708f8fSGustavo F. Padovan 
7016e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
70170a708f8fSGustavo F. Padovan 		goto drop;
70180a708f8fSGustavo F. Padovan 
70192edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
702006ae3314SMarcel Holtmann 	bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
70212edf870dSMarcel Holtmann 	bt_cb(skb)->psm = psm;
70222edf870dSMarcel Holtmann 
702380b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
702484104b24SAndrei Emeltchenko 		return;
70250a708f8fSGustavo F. Padovan 
70260a708f8fSGustavo F. Padovan drop:
70270a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70280a708f8fSGustavo F. Padovan }
70290a708f8fSGustavo F. Padovan 
703072f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn,
7031d9b88702SAndrei Emeltchenko 			      struct sk_buff *skb)
70329f69bda6SGustavo F. Padovan {
7033b99707d7SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
703423691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
70359f69bda6SGustavo F. Padovan 
7036b99707d7SMarcel Holtmann 	if (hcon->type != LE_LINK)
7037b99707d7SMarcel Holtmann 		goto drop;
7038b99707d7SMarcel Holtmann 
7039af1c0134SJohan Hedberg 	chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
704006ae3314SMarcel Holtmann 					 &hcon->src, &hcon->dst);
704123691d75SGustavo F. Padovan 	if (!chan)
70429f69bda6SGustavo F. Padovan 		goto drop;
70439f69bda6SGustavo F. Padovan 
70445b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
70459f69bda6SGustavo F. Padovan 
7046cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
7047cc8dba2bSMarcel Holtmann 		goto drop;
7048cc8dba2bSMarcel Holtmann 
7049e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
70509f69bda6SGustavo F. Padovan 		goto drop;
70519f69bda6SGustavo F. Padovan 
705280b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
70536810fca7SAndrei Emeltchenko 		return;
70549f69bda6SGustavo F. Padovan 
70559f69bda6SGustavo F. Padovan drop:
70569f69bda6SGustavo F. Padovan 	kfree_skb(skb);
70579f69bda6SGustavo F. Padovan }
70589f69bda6SGustavo F. Padovan 
70590a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
70600a708f8fSGustavo F. Padovan {
70610a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
70620a708f8fSGustavo F. Padovan 	u16 cid, len;
70630a708f8fSGustavo F. Padovan 	__le16 psm;
70640a708f8fSGustavo F. Padovan 
70650a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
70660a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
70670a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
70680a708f8fSGustavo F. Padovan 
70690a708f8fSGustavo F. Padovan 	if (len != skb->len) {
70700a708f8fSGustavo F. Padovan 		kfree_skb(skb);
70710a708f8fSGustavo F. Padovan 		return;
70720a708f8fSGustavo F. Padovan 	}
70730a708f8fSGustavo F. Padovan 
70740a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
70750a708f8fSGustavo F. Padovan 
70760a708f8fSGustavo F. Padovan 	switch (cid) {
70770a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
70780a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
70790a708f8fSGustavo F. Padovan 		break;
70800a708f8fSGustavo F. Padovan 
70810a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7082097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
70830181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
70840a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
70850a708f8fSGustavo F. Padovan 		break;
70860a708f8fSGustavo F. Padovan 
7087073d1cf3SJohan Hedberg 	case L2CAP_CID_ATT:
708872f78356SMarcel Holtmann 		l2cap_att_channel(conn, skb);
70899f69bda6SGustavo F. Padovan 		break;
70909f69bda6SGustavo F. Padovan 
7091a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7092a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7093a2877629SMarcel Holtmann 		break;
7094a2877629SMarcel Holtmann 
7095b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
7096b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
7097b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
7098b501d6a1SAnderson Briglia 		break;
7099b501d6a1SAnderson Briglia 
71000a708f8fSGustavo F. Padovan 	default:
71010a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
71020a708f8fSGustavo F. Padovan 		break;
71030a708f8fSGustavo F. Padovan 	}
71040a708f8fSGustavo F. Padovan }
71050a708f8fSGustavo F. Padovan 
71060a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
71070a708f8fSGustavo F. Padovan 
7108686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
71090a708f8fSGustavo F. Padovan {
71100a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
711123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
71120a708f8fSGustavo F. Padovan 
71136ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
71140a708f8fSGustavo F. Padovan 
71150a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
711623691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
711723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
711889bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
71190a708f8fSGustavo F. Padovan 			continue;
71200a708f8fSGustavo F. Padovan 
71217eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
71220a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
712343bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71240a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
71250a708f8fSGustavo F. Padovan 			exact++;
71267eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
71270a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
712843bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71290a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
71300a708f8fSGustavo F. Padovan 		}
71310a708f8fSGustavo F. Padovan 	}
713223691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
71330a708f8fSGustavo F. Padovan 
71340a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
71350a708f8fSGustavo F. Padovan }
71360a708f8fSGustavo F. Padovan 
71379e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
71380a708f8fSGustavo F. Padovan {
71390a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
71400a708f8fSGustavo F. Padovan 
71416ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
71420a708f8fSGustavo F. Padovan 
71430a708f8fSGustavo F. Padovan 	if (!status) {
7144baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
71450a708f8fSGustavo F. Padovan 		if (conn)
71460a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
7147ba6fc317SAndrei Emeltchenko 	} else {
7148e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7149ba6fc317SAndrei Emeltchenko 	}
71500a708f8fSGustavo F. Padovan }
71510a708f8fSGustavo F. Padovan 
7152686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
71530a708f8fSGustavo F. Padovan {
71540a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
71550a708f8fSGustavo F. Padovan 
71560a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
71570a708f8fSGustavo F. Padovan 
7158686ebf28SUlisses Furquim 	if (!conn)
71599f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
71600a708f8fSGustavo F. Padovan 	return conn->disc_reason;
71610a708f8fSGustavo F. Padovan }
71620a708f8fSGustavo F. Padovan 
71639e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
71640a708f8fSGustavo F. Padovan {
71650a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
71660a708f8fSGustavo F. Padovan 
7167e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
71680a708f8fSGustavo F. Padovan }
71690a708f8fSGustavo F. Padovan 
71704343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
71710a708f8fSGustavo F. Padovan {
7172715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
71730a708f8fSGustavo F. Padovan 		return;
71740a708f8fSGustavo F. Padovan 
71750a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
71764343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7177ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
71784343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
71790f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
71800a708f8fSGustavo F. Padovan 	} else {
71814343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7182c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
71830a708f8fSGustavo F. Padovan 	}
71840a708f8fSGustavo F. Padovan }
71850a708f8fSGustavo F. Padovan 
7186686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
71870a708f8fSGustavo F. Padovan {
71880a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
718948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
71900a708f8fSGustavo F. Padovan 
71910a708f8fSGustavo F. Padovan 	if (!conn)
71920a708f8fSGustavo F. Padovan 		return 0;
71930a708f8fSGustavo F. Padovan 
719489d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
71950a708f8fSGustavo F. Padovan 
7196160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
719735d4adccSHemant Gupta 		if (!status && encrypt)
7198160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
719917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
7200160dc6acSVinicius Costa Gomes 	}
7201160dc6acSVinicius Costa Gomes 
72023df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
72030a708f8fSGustavo F. Padovan 
72043df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
72056be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
72060a708f8fSGustavo F. Padovan 
720789d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
720889d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7209f1cb9af5SVinicius Costa Gomes 
721078eb2f98SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
721178eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
721278eb2f98SAndrei Emeltchenko 			continue;
721378eb2f98SAndrei Emeltchenko 		}
721478eb2f98SAndrei Emeltchenko 
7215073d1cf3SJohan Hedberg 		if (chan->scid == L2CAP_CID_ATT) {
7216f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
7217f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
7218cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
7219f1cb9af5SVinicius Costa Gomes 			}
7220f1cb9af5SVinicius Costa Gomes 
72216be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
7222f1cb9af5SVinicius Costa Gomes 			continue;
7223f1cb9af5SVinicius Costa Gomes 		}
7224f1cb9af5SVinicius Costa Gomes 
722596eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
72266be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72270a708f8fSGustavo F. Padovan 			continue;
72280a708f8fSGustavo F. Padovan 		}
72290a708f8fSGustavo F. Padovan 
723089bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
723189bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7232d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
72334343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
72346be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72350a708f8fSGustavo F. Padovan 			continue;
72360a708f8fSGustavo F. Padovan 		}
72370a708f8fSGustavo F. Padovan 
723889bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
72396d3c15daSJohan Hedberg 			if (!status)
724093c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
72416d3c15daSJohan Hedberg 			else
7242ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
724389bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
72440a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7245df3c3931SJohan Hedberg 			__u16 res, stat;
72460a708f8fSGustavo F. Padovan 
72470a708f8fSGustavo F. Padovan 			if (!status) {
7248bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7249df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7250df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
72512dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7252df3c3931SJohan Hedberg 				} else {
7253acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7254df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7255df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7256df3c3931SJohan Hedberg 				}
72570a708f8fSGustavo F. Padovan 			} else {
7258acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7259ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7260df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7261df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
72620a708f8fSGustavo F. Padovan 			}
72630a708f8fSGustavo F. Padovan 
7264fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7265fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7266df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7267df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7268fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7269fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
72702d369359SMat Martineau 
72712d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
72722d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
72732d369359SMat Martineau 				char buf[128];
72742d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
72752d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
72762d369359SMat Martineau 					       L2CAP_CONF_REQ,
72772d369359SMat Martineau 					       l2cap_build_conf_req(chan, buf),
72782d369359SMat Martineau 					       buf);
72792d369359SMat Martineau 				chan->num_conf_req++;
72802d369359SMat Martineau 			}
72810a708f8fSGustavo F. Padovan 		}
72820a708f8fSGustavo F. Padovan 
72836be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
72840a708f8fSGustavo F. Padovan 	}
72850a708f8fSGustavo F. Padovan 
72863df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
72870a708f8fSGustavo F. Padovan 
72880a708f8fSGustavo F. Padovan 	return 0;
72890a708f8fSGustavo F. Padovan }
72900a708f8fSGustavo F. Padovan 
7291686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
72920a708f8fSGustavo F. Padovan {
72930a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7294d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
7295d73a0988SAndrei Emeltchenko 	int len;
72960a708f8fSGustavo F. Padovan 
72971d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
72981d13a254SAndrei Emeltchenko 	if (!conn && hcon->hdev->dev_type != HCI_BREDR)
72991d13a254SAndrei Emeltchenko 		goto drop;
73000a708f8fSGustavo F. Padovan 
73010a708f8fSGustavo F. Padovan 	if (!conn)
7302baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
73030a708f8fSGustavo F. Padovan 
73040a708f8fSGustavo F. Padovan 	if (!conn)
73050a708f8fSGustavo F. Padovan 		goto drop;
73060a708f8fSGustavo F. Padovan 
73070a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
73080a708f8fSGustavo F. Padovan 
7309d73a0988SAndrei Emeltchenko 	switch (flags) {
7310d73a0988SAndrei Emeltchenko 	case ACL_START:
7311d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7312d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
73130a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
73140a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
73150a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
73160a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
73170a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
73180a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73190a708f8fSGustavo F. Padovan 		}
73200a708f8fSGustavo F. Padovan 
73210a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
73220a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
73230a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
73240a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73250a708f8fSGustavo F. Padovan 			goto drop;
73260a708f8fSGustavo F. Padovan 		}
73270a708f8fSGustavo F. Padovan 
73280a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
73290a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
73300a708f8fSGustavo F. Padovan 
73310a708f8fSGustavo F. Padovan 		if (len == skb->len) {
73320a708f8fSGustavo F. Padovan 			/* Complete frame received */
73330a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
73340a708f8fSGustavo F. Padovan 			return 0;
73350a708f8fSGustavo F. Padovan 		}
73360a708f8fSGustavo F. Padovan 
73370a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
73380a708f8fSGustavo F. Padovan 
73390a708f8fSGustavo F. Padovan 		if (skb->len > len) {
73400a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
73410a708f8fSGustavo F. Padovan 			       skb->len, len);
73420a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73430a708f8fSGustavo F. Padovan 			goto drop;
73440a708f8fSGustavo F. Padovan 		}
73450a708f8fSGustavo F. Padovan 
73460a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
73478bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
73480a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
73490a708f8fSGustavo F. Padovan 			goto drop;
73500a708f8fSGustavo F. Padovan 
73510a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73520a708f8fSGustavo F. Padovan 					  skb->len);
73530a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7354d73a0988SAndrei Emeltchenko 		break;
7355d73a0988SAndrei Emeltchenko 
7356d73a0988SAndrei Emeltchenko 	case ACL_CONT:
73570a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
73580a708f8fSGustavo F. Padovan 
73590a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
73600a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
73610a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73620a708f8fSGustavo F. Padovan 			goto drop;
73630a708f8fSGustavo F. Padovan 		}
73640a708f8fSGustavo F. Padovan 
73650a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
73660a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
73670a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
73680a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
73690a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
73700a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
73710a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73720a708f8fSGustavo F. Padovan 			goto drop;
73730a708f8fSGustavo F. Padovan 		}
73740a708f8fSGustavo F. Padovan 
73750a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73760a708f8fSGustavo F. Padovan 					  skb->len);
73770a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
73780a708f8fSGustavo F. Padovan 
73790a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7380c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7381c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7382c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7383c4e5bafaSJohan Hedberg 			 */
7384c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
73850a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7386c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
73870a708f8fSGustavo F. Padovan 		}
7388d73a0988SAndrei Emeltchenko 		break;
73890a708f8fSGustavo F. Padovan 	}
73900a708f8fSGustavo F. Padovan 
73910a708f8fSGustavo F. Padovan drop:
73920a708f8fSGustavo F. Padovan 	kfree_skb(skb);
73930a708f8fSGustavo F. Padovan 	return 0;
73940a708f8fSGustavo F. Padovan }
73950a708f8fSGustavo F. Padovan 
73960a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
73970a708f8fSGustavo F. Padovan {
739823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
73990a708f8fSGustavo F. Padovan 
7400333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
74010a708f8fSGustavo F. Padovan 
740223691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7403fcb73338SAndrei Emeltchenko 		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
74047eafc59eSMarcel Holtmann 			   &c->src, &c->dst,
740589bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
740623691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
740723691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
74080a708f8fSGustavo F. Padovan 	}
74090a708f8fSGustavo F. Padovan 
7410333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
74110a708f8fSGustavo F. Padovan 
74120a708f8fSGustavo F. Padovan 	return 0;
74130a708f8fSGustavo F. Padovan }
74140a708f8fSGustavo F. Padovan 
74150a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
74160a708f8fSGustavo F. Padovan {
74170a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
74180a708f8fSGustavo F. Padovan }
74190a708f8fSGustavo F. Padovan 
74200a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
74210a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
74220a708f8fSGustavo F. Padovan 	.read		= seq_read,
74230a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
74240a708f8fSGustavo F. Padovan 	.release	= single_release,
74250a708f8fSGustavo F. Padovan };
74260a708f8fSGustavo F. Padovan 
74270a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
74280a708f8fSGustavo F. Padovan 
742964274518SGustavo F. Padovan int __init l2cap_init(void)
74300a708f8fSGustavo F. Padovan {
74310a708f8fSGustavo F. Padovan 	int err;
74320a708f8fSGustavo F. Padovan 
7433bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
74340a708f8fSGustavo F. Padovan 	if (err < 0)
74350a708f8fSGustavo F. Padovan 		return err;
74360a708f8fSGustavo F. Padovan 
74371120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
74381120e4bfSMarcel Holtmann 		return 0;
74391120e4bfSMarcel Holtmann 
74402d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
74412d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
74420a708f8fSGustavo F. Padovan 
7443f15b8ecfSJohan Hedberg 	debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs,
7444f15b8ecfSJohan Hedberg 			   &le_max_credits);
7445f15b8ecfSJohan Hedberg 	debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
7446f15b8ecfSJohan Hedberg 			   &le_default_mps);
7447f15b8ecfSJohan Hedberg 
74480a708f8fSGustavo F. Padovan 	return 0;
74490a708f8fSGustavo F. Padovan }
74500a708f8fSGustavo F. Padovan 
745164274518SGustavo F. Padovan void l2cap_exit(void)
74520a708f8fSGustavo F. Padovan {
74530a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7454bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
74550a708f8fSGustavo F. Padovan }
74560a708f8fSGustavo F. Padovan 
74570a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
74580a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7459