xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision e77af755)
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 
520a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
530a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
544519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
554519de9aSGustavo F. Padovan 			   void *data);
56710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
575e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
580a708f8fSGustavo F. Padovan 
59d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
60608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
61608bcc6dSMat Martineau 
624f1654e0SMarcel Holtmann static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type)
634f1654e0SMarcel Holtmann {
644f1654e0SMarcel Holtmann 	if (hcon->type == LE_LINK) {
654f1654e0SMarcel Holtmann 		if (type == ADDR_LE_DEV_PUBLIC)
664f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
674f1654e0SMarcel Holtmann 		else
684f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
694f1654e0SMarcel Holtmann 	}
704f1654e0SMarcel Holtmann 
714f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
724f1654e0SMarcel Holtmann }
734f1654e0SMarcel Holtmann 
740a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
7571ba0e56SGustavo F. Padovan 
762d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
772d792818SGustavo Padovan 						   u16 cid)
780a708f8fSGustavo F. Padovan {
793df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
80baa7e1faSGustavo F. Padovan 
813df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
823df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
833df91ea2SAndrei Emeltchenko 			return c;
840a708f8fSGustavo F. Padovan 	}
853df91ea2SAndrei Emeltchenko 	return NULL;
86baa7e1faSGustavo F. Padovan }
870a708f8fSGustavo F. Padovan 
882d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
892d792818SGustavo Padovan 						   u16 cid)
900a708f8fSGustavo F. Padovan {
913df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
92baa7e1faSGustavo F. Padovan 
933df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
943df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
953df91ea2SAndrei Emeltchenko 			return c;
960a708f8fSGustavo F. Padovan 	}
973df91ea2SAndrei Emeltchenko 	return NULL;
98baa7e1faSGustavo F. Padovan }
990a708f8fSGustavo F. Padovan 
1000a708f8fSGustavo F. Padovan /* Find channel with given SCID.
101ef191adeSMat Martineau  * Returns locked channel. */
1022d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1032d792818SGustavo Padovan 						 u16 cid)
1040a708f8fSGustavo F. Padovan {
10548454079SGustavo F. Padovan 	struct l2cap_chan *c;
106baa7e1faSGustavo F. Padovan 
1073df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
108baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
109ef191adeSMat Martineau 	if (c)
110ef191adeSMat Martineau 		l2cap_chan_lock(c);
1113df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1123df91ea2SAndrei Emeltchenko 
11348454079SGustavo F. Padovan 	return c;
1140a708f8fSGustavo F. Padovan }
1150a708f8fSGustavo F. Padovan 
116b1a130b7SMat Martineau /* Find channel with given DCID.
117b1a130b7SMat Martineau  * Returns locked channel.
118b1a130b7SMat Martineau  */
119b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
120b1a130b7SMat Martineau 						 u16 cid)
121b1a130b7SMat Martineau {
122b1a130b7SMat Martineau 	struct l2cap_chan *c;
123b1a130b7SMat Martineau 
124b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
125b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
126b1a130b7SMat Martineau 	if (c)
127b1a130b7SMat Martineau 		l2cap_chan_lock(c);
128b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
129b1a130b7SMat Martineau 
130b1a130b7SMat Martineau 	return c;
131b1a130b7SMat Martineau }
132b1a130b7SMat Martineau 
1332d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1342d792818SGustavo Padovan 						    u8 ident)
1350a708f8fSGustavo F. Padovan {
1363df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
137baa7e1faSGustavo F. Padovan 
1383df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1393df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1403df91ea2SAndrei Emeltchenko 			return c;
1410a708f8fSGustavo F. Padovan 	}
1423df91ea2SAndrei Emeltchenko 	return NULL;
143baa7e1faSGustavo F. Padovan }
1440a708f8fSGustavo F. Padovan 
1455b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1465b155ef9SMat Martineau 						  u8 ident)
1475b155ef9SMat Martineau {
1485b155ef9SMat Martineau 	struct l2cap_chan *c;
1495b155ef9SMat Martineau 
1505b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1515b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1525b155ef9SMat Martineau 	if (c)
1535b155ef9SMat Martineau 		l2cap_chan_lock(c);
1545b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1555b155ef9SMat Martineau 
1565b155ef9SMat Martineau 	return c;
1575b155ef9SMat Martineau }
1585b155ef9SMat Martineau 
15923691d75SGustavo F. Padovan static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
1609e4425ffSGustavo F. Padovan {
16123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1629e4425ffSGustavo F. Padovan 
16323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
1647eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
16523691d75SGustavo F. Padovan 			return c;
1669e4425ffSGustavo F. Padovan 	}
167250938cbSSzymon Janc 	return NULL;
168250938cbSSzymon Janc }
1699e4425ffSGustavo F. Padovan 
1709e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1719e4425ffSGustavo F. Padovan {
17273b2ec18SGustavo F. Padovan 	int err;
17373b2ec18SGustavo F. Padovan 
174333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1759e4425ffSGustavo F. Padovan 
17623691d75SGustavo F. Padovan 	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
17773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
17873b2ec18SGustavo F. Padovan 		goto done;
1799e4425ffSGustavo F. Padovan 	}
1809e4425ffSGustavo F. Padovan 
18173b2ec18SGustavo F. Padovan 	if (psm) {
1829e4425ffSGustavo F. Padovan 		chan->psm = psm;
1839e4425ffSGustavo F. Padovan 		chan->sport = psm;
18473b2ec18SGustavo F. Padovan 		err = 0;
18573b2ec18SGustavo F. Padovan 	} else {
18673b2ec18SGustavo F. Padovan 		u16 p;
1879e4425ffSGustavo F. Padovan 
18873b2ec18SGustavo F. Padovan 		err = -EINVAL;
18973b2ec18SGustavo F. Padovan 		for (p = 0x1001; p < 0x1100; p += 2)
19023691d75SGustavo F. Padovan 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
19173b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
19273b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
19373b2ec18SGustavo F. Padovan 				err = 0;
19473b2ec18SGustavo F. Padovan 				break;
19573b2ec18SGustavo F. Padovan 			}
19673b2ec18SGustavo F. Padovan 	}
19773b2ec18SGustavo F. Padovan 
19873b2ec18SGustavo F. Padovan done:
199333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
20073b2ec18SGustavo F. Padovan 	return err;
2019e4425ffSGustavo F. Padovan }
2029e4425ffSGustavo F. Padovan 
2039e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2049e4425ffSGustavo F. Padovan {
205333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2069e4425ffSGustavo F. Padovan 
2079e4425ffSGustavo F. Padovan 	chan->scid = scid;
2089e4425ffSGustavo F. Padovan 
209333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2109e4425ffSGustavo F. Padovan 
2119e4425ffSGustavo F. Padovan 	return 0;
2129e4425ffSGustavo F. Padovan }
2139e4425ffSGustavo F. Padovan 
214baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2150a708f8fSGustavo F. Padovan {
216e77af755SJohan Hedberg 	u16 cid, dyn_end;
2170a708f8fSGustavo F. Padovan 
218e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
219e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
220e77af755SJohan Hedberg 	else
221e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
222e77af755SJohan Hedberg 
223e77af755SJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
224baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2250a708f8fSGustavo F. Padovan 			return cid;
2260a708f8fSGustavo F. Padovan 	}
2270a708f8fSGustavo F. Padovan 
2280a708f8fSGustavo F. Padovan 	return 0;
2290a708f8fSGustavo F. Padovan }
2300a708f8fSGustavo F. Padovan 
231f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
23289bc500eSGustavo F. Padovan {
23342d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
234badaaa00SGustavo F. Padovan 	       state_to_string(state));
235badaaa00SGustavo F. Padovan 
23689bc500eSGustavo F. Padovan 	chan->state = state;
23753f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
23889bc500eSGustavo F. Padovan }
23989bc500eSGustavo F. Padovan 
240f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
241f8e73017SGustavo Padovan 						int state, int err)
2422e0052e4SAndrei Emeltchenko {
243f8e73017SGustavo Padovan 	chan->state = state;
24453f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2452e0052e4SAndrei Emeltchenko }
2462e0052e4SAndrei Emeltchenko 
2472e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2482e0052e4SAndrei Emeltchenko {
249f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2502e0052e4SAndrei Emeltchenko }
2512e0052e4SAndrei Emeltchenko 
2524239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2534239d16fSMat Martineau {
2544239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2554239d16fSMat Martineau 	    chan->retrans_timeout) {
2564239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2574239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2584239d16fSMat Martineau 	}
2594239d16fSMat Martineau }
2604239d16fSMat Martineau 
2614239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2624239d16fSMat Martineau {
2634239d16fSMat Martineau 	__clear_retrans_timer(chan);
2644239d16fSMat Martineau 	if (chan->monitor_timeout) {
2654239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
2664239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
2674239d16fSMat Martineau 	}
2684239d16fSMat Martineau }
2694239d16fSMat Martineau 
270608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
271608bcc6dSMat Martineau 					       u16 seq)
272608bcc6dSMat Martineau {
273608bcc6dSMat Martineau 	struct sk_buff *skb;
274608bcc6dSMat Martineau 
275608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
276608bcc6dSMat Martineau 		if (bt_cb(skb)->control.txseq == seq)
277608bcc6dSMat Martineau 			return skb;
278608bcc6dSMat Martineau 	}
279608bcc6dSMat Martineau 
280608bcc6dSMat Martineau 	return NULL;
281608bcc6dSMat Martineau }
282608bcc6dSMat Martineau 
2833c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
2843c588192SMat Martineau 
2853c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
2863c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
2873c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
2883c588192SMat Martineau  * list in an array, where membership in the list can also be checked
2893c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
2903c588192SMat Martineau  * and removed from the head in constant time, without further memory
2913c588192SMat Martineau  * allocs or frees.
2923c588192SMat Martineau  */
2933c588192SMat Martineau 
2943c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
2953c588192SMat Martineau {
2963c588192SMat Martineau 	size_t alloc_size, i;
2973c588192SMat Martineau 
2983c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
2993c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3003c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3013c588192SMat Martineau 	 */
3023c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3033c588192SMat Martineau 
3043c588192SMat Martineau 	seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
3053c588192SMat Martineau 	if (!seq_list->list)
3063c588192SMat Martineau 		return -ENOMEM;
3073c588192SMat Martineau 
3083c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3093c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3103c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3113c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3123c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3133c588192SMat Martineau 
3143c588192SMat Martineau 	return 0;
3153c588192SMat Martineau }
3163c588192SMat Martineau 
3173c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3183c588192SMat Martineau {
3193c588192SMat Martineau 	kfree(seq_list->list);
3203c588192SMat Martineau }
3213c588192SMat Martineau 
3223c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3233c588192SMat Martineau 					   u16 seq)
3243c588192SMat Martineau {
3253c588192SMat Martineau 	/* Constant-time check for list membership */
3263c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3273c588192SMat Martineau }
3283c588192SMat Martineau 
3293c588192SMat Martineau static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq)
3303c588192SMat Martineau {
3313c588192SMat Martineau 	u16 mask = seq_list->mask;
3323c588192SMat Martineau 
3333c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) {
3343c588192SMat Martineau 		/* In case someone tries to pop the head of an empty list */
3353c588192SMat Martineau 		return L2CAP_SEQ_LIST_CLEAR;
3363c588192SMat Martineau 	} else if (seq_list->head == seq) {
3373c588192SMat Martineau 		/* Head can be removed in constant time */
3383c588192SMat Martineau 		seq_list->head = seq_list->list[seq & mask];
3393c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3403c588192SMat Martineau 
3413c588192SMat Martineau 		if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3423c588192SMat Martineau 			seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3433c588192SMat Martineau 			seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3443c588192SMat Martineau 		}
3453c588192SMat Martineau 	} else {
3463c588192SMat Martineau 		/* Walk the list to find the sequence number */
3473c588192SMat Martineau 		u16 prev = seq_list->head;
3483c588192SMat Martineau 		while (seq_list->list[prev & mask] != seq) {
3493c588192SMat Martineau 			prev = seq_list->list[prev & mask];
3503c588192SMat Martineau 			if (prev == L2CAP_SEQ_LIST_TAIL)
3513c588192SMat Martineau 				return L2CAP_SEQ_LIST_CLEAR;
3523c588192SMat Martineau 		}
3533c588192SMat Martineau 
3543c588192SMat Martineau 		/* Unlink the number from the list and clear it */
3553c588192SMat Martineau 		seq_list->list[prev & mask] = seq_list->list[seq & mask];
3563c588192SMat Martineau 		seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3573c588192SMat Martineau 		if (seq_list->tail == seq)
3583c588192SMat Martineau 			seq_list->tail = prev;
3593c588192SMat Martineau 	}
3603c588192SMat Martineau 	return seq;
3613c588192SMat Martineau }
3623c588192SMat Martineau 
3633c588192SMat Martineau static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3643c588192SMat Martineau {
3653c588192SMat Martineau 	/* Remove the head in constant time */
3663c588192SMat Martineau 	return l2cap_seq_list_remove(seq_list, seq_list->head);
3673c588192SMat Martineau }
3683c588192SMat Martineau 
3693c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3703c588192SMat Martineau {
3713c588192SMat Martineau 	u16 i;
372f522ae36SGustavo Padovan 
373f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
374f522ae36SGustavo Padovan 		return;
375f522ae36SGustavo Padovan 
3763c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3773c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3783c588192SMat Martineau 
3793c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3803c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3813c588192SMat Martineau }
3823c588192SMat Martineau 
3833c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3843c588192SMat Martineau {
3853c588192SMat Martineau 	u16 mask = seq_list->mask;
3863c588192SMat Martineau 
3873c588192SMat Martineau 	/* All appends happen in constant time */
3883c588192SMat Martineau 
389f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
390f522ae36SGustavo Padovan 		return;
391f522ae36SGustavo Padovan 
3923c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
3933c588192SMat Martineau 		seq_list->head = seq;
3943c588192SMat Martineau 	else
3953c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
3963c588192SMat Martineau 
3973c588192SMat Martineau 	seq_list->tail = seq;
3983c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
3993c588192SMat Martineau }
4003c588192SMat Martineau 
401721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
402ab07801dSGustavo F. Padovan {
403721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
404721c4181SGustavo F. Padovan 					       chan_timer.work);
4053df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
406ab07801dSGustavo F. Padovan 	int reason;
407ab07801dSGustavo F. Padovan 
408e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
409ab07801dSGustavo F. Padovan 
4103df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4116be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
412ab07801dSGustavo F. Padovan 
41389bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
414ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
41589bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
416ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
417ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
418ab07801dSGustavo F. Padovan 	else
419ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
420ab07801dSGustavo F. Padovan 
4210f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
422ab07801dSGustavo F. Padovan 
4236be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
424ab07801dSGustavo F. Padovan 
42580b98027SGustavo Padovan 	chan->ops->close(chan);
4263df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4273df91ea2SAndrei Emeltchenko 
428371fd835SUlisses Furquim 	l2cap_chan_put(chan);
429ab07801dSGustavo F. Padovan }
430ab07801dSGustavo F. Padovan 
431eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4320a708f8fSGustavo F. Padovan {
43348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4340a708f8fSGustavo F. Padovan 
43548454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
43648454079SGustavo F. Padovan 	if (!chan)
43748454079SGustavo F. Padovan 		return NULL;
4380a708f8fSGustavo F. Padovan 
439c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
440c03b355eSAndrei Emeltchenko 
441333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
44223691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
443333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
44423691d75SGustavo F. Padovan 
445721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
446ab07801dSGustavo F. Padovan 
44789bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
44889bc500eSGustavo F. Padovan 
449144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
45071ba0e56SGustavo F. Padovan 
4512827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4522827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4532827011fSMat Martineau 
454eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
455abc545b8SSzymon Janc 
45648454079SGustavo F. Padovan 	return chan;
4570a708f8fSGustavo F. Padovan }
4580a708f8fSGustavo F. Padovan 
459144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4606ff5abbfSGustavo F. Padovan {
461144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
462144ad330SSyam Sidhardhan 
4634af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4644af66c69SJaganath Kanakkassery 
465333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46623691d75SGustavo F. Padovan 	list_del(&chan->global_l);
467333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
46823691d75SGustavo F. Padovan 
4694af66c69SJaganath Kanakkassery 	kfree(chan);
4706ff5abbfSGustavo F. Padovan }
4716ff5abbfSGustavo F. Padovan 
47230648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
47330648372SJaganath Kanakkassery {
474144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
47530648372SJaganath Kanakkassery 
476144ad330SSyam Sidhardhan 	kref_get(&c->kref);
47730648372SJaganath Kanakkassery }
47830648372SJaganath Kanakkassery 
47930648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
48030648372SJaganath Kanakkassery {
481144ad330SSyam Sidhardhan 	BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount));
48230648372SJaganath Kanakkassery 
483144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
48430648372SJaganath Kanakkassery }
48530648372SJaganath Kanakkassery 
486bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
487bd4b1653SAndrei Emeltchenko {
488bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
489bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
490bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
491bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
492c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
493bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
494bd4b1653SAndrei Emeltchenko 
495bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
496bd4b1653SAndrei Emeltchenko }
497bd4b1653SAndrei Emeltchenko 
49838319713SJohan Hedberg void l2cap_le_flowctl_init(struct l2cap_chan *chan)
49938319713SJohan Hedberg {
50038319713SJohan Hedberg 	chan->imtu = L2CAP_DEFAULT_MTU;
50138319713SJohan Hedberg 	chan->omtu = L2CAP_LE_MIN_MTU;
50238319713SJohan Hedberg 	chan->mode = L2CAP_MODE_LE_FLOWCTL;
5030cd75f7eSJohan Hedberg 	chan->tx_credits = 0;
5040cd75f7eSJohan Hedberg 	chan->rx_credits = L2CAP_LE_MAX_CREDITS;
5053916aed8SJohan Hedberg 
5063916aed8SJohan Hedberg 	if (chan->imtu < L2CAP_LE_DEFAULT_MPS)
5073916aed8SJohan Hedberg 		chan->mps = chan->imtu;
5083916aed8SJohan Hedberg 	else
5093916aed8SJohan Hedberg 		chan->mps = L2CAP_LE_DEFAULT_MPS;
51038319713SJohan Hedberg }
51138319713SJohan Hedberg 
51293c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5130a708f8fSGustavo F. Padovan {
5140a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
515097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5160a708f8fSGustavo F. Padovan 
5179f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5180a708f8fSGustavo F. Padovan 
5198c1d787bSGustavo F. Padovan 	chan->conn = conn;
5200a708f8fSGustavo F. Padovan 
5215491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5225491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
523b62f328bSVille Tervo 		if (conn->hcon->type == LE_LINK) {
524aeddd075SJohan Hedberg 			if (chan->dcid == L2CAP_CID_ATT) {
5256fcb06a2SAndre Guedes 				chan->omtu = L2CAP_DEFAULT_MTU;
526073d1cf3SJohan Hedberg 				chan->scid = L2CAP_CID_ATT;
527aeddd075SJohan Hedberg 			} else {
5289f22398cSJohan Hedberg 				chan->scid = l2cap_alloc_cid(conn);
529aeddd075SJohan Hedberg 			}
530b62f328bSVille Tervo 		} else {
5310a708f8fSGustavo F. Padovan 			/* Alloc CID for connection-oriented socket */
532fe4128e0SGustavo F. Padovan 			chan->scid = l2cap_alloc_cid(conn);
5330c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
534b62f328bSVille Tervo 		}
5355491120eSAndrei Emeltchenko 		break;
5365491120eSAndrei Emeltchenko 
5375491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5380a708f8fSGustavo F. Padovan 		/* Connectionless socket */
539fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
540fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5410c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5425491120eSAndrei Emeltchenko 		break;
5435491120eSAndrei Emeltchenko 
544416fa752SAndrei Emeltchenko 	case L2CAP_CHAN_CONN_FIX_A2MP:
545416fa752SAndrei Emeltchenko 		chan->scid = L2CAP_CID_A2MP;
546416fa752SAndrei Emeltchenko 		chan->dcid = L2CAP_CID_A2MP;
547416fa752SAndrei Emeltchenko 		chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
548416fa752SAndrei Emeltchenko 		chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
549416fa752SAndrei Emeltchenko 		break;
550416fa752SAndrei Emeltchenko 
5515491120eSAndrei Emeltchenko 	default:
5520a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
553fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
554fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5550c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5560a708f8fSGustavo F. Padovan 	}
5570a708f8fSGustavo F. Padovan 
5588f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5598f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5608f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5618f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5628f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5638936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5648f7975b1SAndrei Emeltchenko 
565371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
566baa7e1faSGustavo F. Padovan 
5675ee9891dSJohan Hedberg 	hci_conn_hold(conn->hcon);
5685ee9891dSJohan Hedberg 
5693df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
570643162a8SAndrei Emeltchenko }
571643162a8SAndrei Emeltchenko 
572466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
573643162a8SAndrei Emeltchenko {
574643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
575643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
5763df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
5770a708f8fSGustavo F. Padovan }
5780a708f8fSGustavo F. Padovan 
579466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
5800a708f8fSGustavo F. Padovan {
5818c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
5820a708f8fSGustavo F. Padovan 
583c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
5840a708f8fSGustavo F. Padovan 
58549208c9cSGustavo F. Padovan 	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
5860a708f8fSGustavo F. Padovan 
5870a708f8fSGustavo F. Padovan 	if (conn) {
58856f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
589baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
5903df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
5913d57dc68SGustavo F. Padovan 
592371fd835SUlisses Furquim 		l2cap_chan_put(chan);
593baa7e1faSGustavo F. Padovan 
5948c1d787bSGustavo F. Padovan 		chan->conn = NULL;
5953cabbfdaSAndrei Emeltchenko 
5963cabbfdaSAndrei Emeltchenko 		if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
59776a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
59856f60984SAndrei Emeltchenko 
59956f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
60056f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6010a708f8fSGustavo F. Padovan 	}
6020a708f8fSGustavo F. Padovan 
603419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
604419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
605419e08c1SAndrei Emeltchenko 
606419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
607419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
608419e08c1SAndrei Emeltchenko 	}
609419e08c1SAndrei Emeltchenko 
610c0df7f6eSAndrei Emeltchenko 	chan->ops->teardown(chan, err);
6116be36555SAndrei Emeltchenko 
6122827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6136ff5abbfSGustavo F. Padovan 		return;
6142ead70b8SGustavo F. Padovan 
615ee556f66SGustavo Padovan 	switch(chan->mode) {
616ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
617ee556f66SGustavo Padovan 		break;
6180a708f8fSGustavo F. Padovan 
61938319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
620177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
62138319713SJohan Hedberg 		break;
62238319713SJohan Hedberg 
623ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6241a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6251a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6261a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6270a708f8fSGustavo F. Padovan 
628f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6290a708f8fSGustavo F. Padovan 
6303c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6313c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
632ee556f66SGustavo Padovan 
633ee556f66SGustavo Padovan 		/* fall through */
634ee556f66SGustavo Padovan 
635ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
636ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
637ee556f66SGustavo Padovan 		break;
6380a708f8fSGustavo F. Padovan 	}
639ee556f66SGustavo Padovan 
640ee556f66SGustavo Padovan 	return;
6410a708f8fSGustavo F. Padovan }
6420a708f8fSGustavo F. Padovan 
64327e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
64427e2d4c8SJohan Hedberg {
64527e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
64627e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
64727e2d4c8SJohan Hedberg 	u16 result;
64827e2d4c8SJohan Hedberg 
64927e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
65027e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHORIZATION;
65127e2d4c8SJohan Hedberg 	else
65227e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
65327e2d4c8SJohan Hedberg 
65427e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
65527e2d4c8SJohan Hedberg 
65627e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
65727e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
6583916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
6590cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
66027e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
66127e2d4c8SJohan Hedberg 
66227e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
66327e2d4c8SJohan Hedberg 		       &rsp);
66427e2d4c8SJohan Hedberg }
66527e2d4c8SJohan Hedberg 
666791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
667791d60f7SJohan Hedberg {
668791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
669791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
670791d60f7SJohan Hedberg 	u16 result;
671791d60f7SJohan Hedberg 
672791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
673791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
674791d60f7SJohan Hedberg 	else
675791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
676791d60f7SJohan Hedberg 
677791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
678791d60f7SJohan Hedberg 
679791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
680791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
681791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
682791d60f7SJohan Hedberg 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
683791d60f7SJohan Hedberg 
684791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
685791d60f7SJohan Hedberg }
686791d60f7SJohan Hedberg 
6870f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
6884519de9aSGustavo F. Padovan {
6894519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6904519de9aSGustavo F. Padovan 
6917eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
6924519de9aSGustavo F. Padovan 
69389bc500eSGustavo F. Padovan 	switch (chan->state) {
6944519de9aSGustavo F. Padovan 	case BT_LISTEN:
695c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
6964519de9aSGustavo F. Padovan 		break;
6974519de9aSGustavo F. Padovan 
6984519de9aSGustavo F. Padovan 	case BT_CONNECTED:
6994519de9aSGustavo F. Padovan 	case BT_CONFIG:
700cea04ce3SJohan Hedberg 		/* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
701cea04ce3SJohan Hedberg 		 * check for chan->psm.
702cea04ce3SJohan Hedberg 		 */
703cea04ce3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
7048d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7055e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
7064519de9aSGustavo F. Padovan 		} else
7074519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
7084519de9aSGustavo F. Padovan 		break;
7094519de9aSGustavo F. Padovan 
7104519de9aSGustavo F. Padovan 	case BT_CONNECT2:
711791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
712791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
713791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
71427e2d4c8SJohan Hedberg 			else if (conn->hcon->type == LE_LINK)
71527e2d4c8SJohan Hedberg 				l2cap_chan_le_connect_reject(chan);
7164519de9aSGustavo F. Padovan 		}
7174519de9aSGustavo F. Padovan 
7184519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7194519de9aSGustavo F. Padovan 		break;
7204519de9aSGustavo F. Padovan 
7214519de9aSGustavo F. Padovan 	case BT_CONNECT:
7224519de9aSGustavo F. Padovan 	case BT_DISCONN:
7234519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
7244519de9aSGustavo F. Padovan 		break;
7254519de9aSGustavo F. Padovan 
7264519de9aSGustavo F. Padovan 	default:
727c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
7284519de9aSGustavo F. Padovan 		break;
7294519de9aSGustavo F. Padovan 	}
7304519de9aSGustavo F. Padovan }
7314519de9aSGustavo F. Padovan 
7324343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
7330a708f8fSGustavo F. Padovan {
7346a974b50SMarcel Holtmann 	switch (chan->chan_type) {
7356a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
7364343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7370a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7380a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
7390a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7400a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
7410a708f8fSGustavo F. Padovan 		default:
7420a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7430a708f8fSGustavo F. Padovan 		}
7446a974b50SMarcel Holtmann 		break;
7453124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
7463124b843SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) {
7473124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
7483124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
7493124b843SMarcel Holtmann 		}
7503124b843SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH)
7513124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
7523124b843SMarcel Holtmann 		else
7533124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
7543124b843SMarcel Holtmann 		break;
7556a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
7566a974b50SMarcel Holtmann 		if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) {
7574343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
7584343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
7590a708f8fSGustavo F. Padovan 
7604343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_HIGH)
7610a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
7620a708f8fSGustavo F. Padovan 			else
7630a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
7646a974b50SMarcel Holtmann 		}
7656a974b50SMarcel Holtmann 		/* fall through */
7666a974b50SMarcel Holtmann 	default:
7674343478fSGustavo F. Padovan 		switch (chan->sec_level) {
7680a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
7690a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
7700a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
7710a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
7720a708f8fSGustavo F. Padovan 		default:
7730a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
7740a708f8fSGustavo F. Padovan 		}
7756a974b50SMarcel Holtmann 		break;
7760a708f8fSGustavo F. Padovan 	}
7770a708f8fSGustavo F. Padovan }
7780a708f8fSGustavo F. Padovan 
7790a708f8fSGustavo F. Padovan /* Service level security */
780d45fc423SGustavo F. Padovan int l2cap_chan_check_security(struct l2cap_chan *chan)
7810a708f8fSGustavo F. Padovan {
7828c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7830a708f8fSGustavo F. Padovan 	__u8 auth_type;
7840a708f8fSGustavo F. Padovan 
785a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
786a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
787a17de2feSJohan Hedberg 
7884343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
7890a708f8fSGustavo F. Padovan 
7904343478fSGustavo F. Padovan 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
7910a708f8fSGustavo F. Padovan }
7920a708f8fSGustavo F. Padovan 
793b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
7940a708f8fSGustavo F. Padovan {
7950a708f8fSGustavo F. Padovan 	u8 id;
7960a708f8fSGustavo F. Padovan 
7970a708f8fSGustavo F. Padovan 	/* Get next available identificator.
7980a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
7990a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
8000a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
8010a708f8fSGustavo F. Padovan 	 */
8020a708f8fSGustavo F. Padovan 
803333055f2SGustavo F. Padovan 	spin_lock(&conn->lock);
8040a708f8fSGustavo F. Padovan 
8050a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
8060a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
8070a708f8fSGustavo F. Padovan 
8080a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
8090a708f8fSGustavo F. Padovan 
810333055f2SGustavo F. Padovan 	spin_unlock(&conn->lock);
8110a708f8fSGustavo F. Padovan 
8120a708f8fSGustavo F. Padovan 	return id;
8130a708f8fSGustavo F. Padovan }
8140a708f8fSGustavo F. Padovan 
8152d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
8162d792818SGustavo Padovan 			   void *data)
8170a708f8fSGustavo F. Padovan {
8180a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
8190a708f8fSGustavo F. Padovan 	u8 flags;
8200a708f8fSGustavo F. Padovan 
8210a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
8220a708f8fSGustavo F. Padovan 
8230a708f8fSGustavo F. Padovan 	if (!skb)
8240a708f8fSGustavo F. Padovan 		return;
8250a708f8fSGustavo F. Padovan 
8260a708f8fSGustavo F. Padovan 	if (lmp_no_flush_capable(conn->hcon->hdev))
8270a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
8280a708f8fSGustavo F. Padovan 	else
8290a708f8fSGustavo F. Padovan 		flags = ACL_START;
8300a708f8fSGustavo F. Padovan 
83114b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
8325e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
83314b12d0bSJaikumar Ganesh 
83473d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
8350a708f8fSGustavo F. Padovan }
8360a708f8fSGustavo F. Padovan 
83702b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
83802b0fbb9SMat Martineau {
83902b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
84002b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
84102b0fbb9SMat Martineau }
84202b0fbb9SMat Martineau 
84373d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
84473d80debSLuiz Augusto von Dentz {
84573d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
84673d80debSLuiz Augusto von Dentz 	u16 flags;
84773d80debSLuiz Augusto von Dentz 
84873d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
84973d80debSLuiz Augusto von Dentz 	       skb->priority);
85073d80debSLuiz Augusto von Dentz 
851d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
852d5f8a75dSMat Martineau 		if (chan->hs_hchan)
853d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
854d5f8a75dSMat Martineau 		else
855d5f8a75dSMat Martineau 			kfree_skb(skb);
856d5f8a75dSMat Martineau 
857d5f8a75dSMat Martineau 		return;
858d5f8a75dSMat Martineau 	}
859d5f8a75dSMat Martineau 
86073d80debSLuiz Augusto von Dentz 	if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
86173d80debSLuiz Augusto von Dentz 	    lmp_no_flush_capable(hcon->hdev))
86273d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
86373d80debSLuiz Augusto von Dentz 	else
86473d80debSLuiz Augusto von Dentz 		flags = ACL_START;
86573d80debSLuiz Augusto von Dentz 
86673d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
86773d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
8680a708f8fSGustavo F. Padovan }
8690a708f8fSGustavo F. Padovan 
870b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
871b5c6aaedSMat Martineau {
872b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
873b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
874b5c6aaedSMat Martineau 
875b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
876b5c6aaedSMat Martineau 		/* S-Frame */
877b5c6aaedSMat Martineau 		control->sframe = 1;
878b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
879b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
880b5c6aaedSMat Martineau 
881b5c6aaedSMat Martineau 		control->sar = 0;
882b5c6aaedSMat Martineau 		control->txseq = 0;
883b5c6aaedSMat Martineau 	} else {
884b5c6aaedSMat Martineau 		/* I-Frame */
885b5c6aaedSMat Martineau 		control->sframe = 0;
886b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
887b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
888b5c6aaedSMat Martineau 
889b5c6aaedSMat Martineau 		control->poll = 0;
890b5c6aaedSMat Martineau 		control->super = 0;
891b5c6aaedSMat Martineau 	}
892b5c6aaedSMat Martineau }
893b5c6aaedSMat Martineau 
894b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
895b5c6aaedSMat Martineau {
896b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
897b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
898b5c6aaedSMat Martineau 
899b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
900b5c6aaedSMat Martineau 		/* S-Frame */
901b5c6aaedSMat Martineau 		control->sframe = 1;
902b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
903b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
904b5c6aaedSMat Martineau 
905b5c6aaedSMat Martineau 		control->sar = 0;
906b5c6aaedSMat Martineau 		control->txseq = 0;
907b5c6aaedSMat Martineau 	} else {
908b5c6aaedSMat Martineau 		/* I-Frame */
909b5c6aaedSMat Martineau 		control->sframe = 0;
910b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
911b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
912b5c6aaedSMat Martineau 
913b5c6aaedSMat Martineau 		control->poll = 0;
914b5c6aaedSMat Martineau 		control->super = 0;
915b5c6aaedSMat Martineau 	}
916b5c6aaedSMat Martineau }
917b5c6aaedSMat Martineau 
918b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
919b5c6aaedSMat Martineau 				    struct sk_buff *skb)
920b5c6aaedSMat Martineau {
921b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
922b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
923b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
924cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
925b5c6aaedSMat Martineau 	} else {
926b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
927b5c6aaedSMat Martineau 					  &bt_cb(skb)->control);
928cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
929b5c6aaedSMat Martineau 	}
930b5c6aaedSMat Martineau }
931b5c6aaedSMat Martineau 
932b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
933b5c6aaedSMat Martineau {
934b5c6aaedSMat Martineau 	u32 packed;
935b5c6aaedSMat Martineau 
936b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
937b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
938b5c6aaedSMat Martineau 
939b5c6aaedSMat Martineau 	if (control->sframe) {
940b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
941b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
942b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
943b5c6aaedSMat Martineau 	} else {
944b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
945b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
946b5c6aaedSMat Martineau 	}
947b5c6aaedSMat Martineau 
948b5c6aaedSMat Martineau 	return packed;
949b5c6aaedSMat Martineau }
950b5c6aaedSMat Martineau 
951b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
952b5c6aaedSMat Martineau {
953b5c6aaedSMat Martineau 	u16 packed;
954b5c6aaedSMat Martineau 
955b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
956b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
957b5c6aaedSMat Martineau 
958b5c6aaedSMat Martineau 	if (control->sframe) {
959b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
960b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
961b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
962b5c6aaedSMat Martineau 	} else {
963b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
964b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
965b5c6aaedSMat Martineau 	}
966b5c6aaedSMat Martineau 
967b5c6aaedSMat Martineau 	return packed;
968b5c6aaedSMat Martineau }
969b5c6aaedSMat Martineau 
970b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
971b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
972b5c6aaedSMat Martineau 				  struct sk_buff *skb)
973b5c6aaedSMat Martineau {
974b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
975b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
976b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
977b5c6aaedSMat Martineau 	} else {
978b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
979b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
980b5c6aaedSMat Martineau 	}
981b5c6aaedSMat Martineau }
982b5c6aaedSMat Martineau 
983ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
984ba7aa64fSGustavo Padovan {
985ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
986ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
987ba7aa64fSGustavo Padovan 	else
988ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
989ba7aa64fSGustavo Padovan }
990ba7aa64fSGustavo Padovan 
991a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
992a67d7f6fSMat Martineau 					       u32 control)
9930a708f8fSGustavo F. Padovan {
9940a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
9950a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
996ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
9970a708f8fSGustavo F. Padovan 
9980a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
99903a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
10000a708f8fSGustavo F. Padovan 
1001a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
10020a708f8fSGustavo F. Padovan 
10030a708f8fSGustavo F. Padovan 	if (!skb)
1004a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
10050a708f8fSGustavo F. Padovan 
10060a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
10070a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1008fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
100988843ab0SAndrei Emeltchenko 
1010a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1011a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1012a67d7f6fSMat Martineau 	else
1013a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
10140a708f8fSGustavo F. Padovan 
101547d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1016a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
101703a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
10180a708f8fSGustavo F. Padovan 	}
10190a708f8fSGustavo F. Padovan 
102073d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1021a67d7f6fSMat Martineau 	return skb;
1022a67d7f6fSMat Martineau }
1023a67d7f6fSMat Martineau 
1024a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1025a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1026a67d7f6fSMat Martineau {
1027a67d7f6fSMat Martineau 	struct sk_buff *skb;
1028a67d7f6fSMat Martineau 	u32 control_field;
1029a67d7f6fSMat Martineau 
1030a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1031a67d7f6fSMat Martineau 
1032a67d7f6fSMat Martineau 	if (!control->sframe)
1033a67d7f6fSMat Martineau 		return;
1034a67d7f6fSMat Martineau 
1035b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1036b99e13adSMat Martineau 		return;
1037b99e13adSMat Martineau 
1038a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1039a67d7f6fSMat Martineau 	    !control->poll)
1040a67d7f6fSMat Martineau 		control->final = 1;
1041a67d7f6fSMat Martineau 
1042a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1043a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1044a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1045a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1046a67d7f6fSMat Martineau 
1047a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1048a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1049a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1050a67d7f6fSMat Martineau 	}
1051a67d7f6fSMat Martineau 
1052a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1053a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1054a67d7f6fSMat Martineau 
1055a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1056a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1057a67d7f6fSMat Martineau 	else
1058a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1059a67d7f6fSMat Martineau 
1060a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1061a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
106273d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
10630a708f8fSGustavo F. Padovan }
10640a708f8fSGustavo F. Padovan 
1065c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
10660a708f8fSGustavo F. Padovan {
1067c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
10680a708f8fSGustavo F. Padovan 
1069c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1070c9e3d5e0SMat Martineau 
1071c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1072c9e3d5e0SMat Martineau 	control.sframe = 1;
1073c9e3d5e0SMat Martineau 	control.poll = poll;
1074c9e3d5e0SMat Martineau 
1075c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1076c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1077c9e3d5e0SMat Martineau 	else
1078c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1079c9e3d5e0SMat Martineau 
1080c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1081c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
10820a708f8fSGustavo F. Padovan }
10830a708f8fSGustavo F. Padovan 
1084b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
10850a708f8fSGustavo F. Padovan {
1086c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
10870a708f8fSGustavo F. Padovan }
10880a708f8fSGustavo F. Padovan 
108993c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
109093c3e8f5SAndrei Emeltchenko {
109193c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
10921df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
10931df7b17aSMarcel Holtmann 	bool amp_available = false;
109493c3e8f5SAndrei Emeltchenko 
10951df7b17aSMarcel Holtmann 	if (!conn->hs_enabled)
10961df7b17aSMarcel Holtmann 		return false;
10971df7b17aSMarcel Holtmann 
10981df7b17aSMarcel Holtmann 	if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
10991df7b17aSMarcel Holtmann 		return false;
11001df7b17aSMarcel Holtmann 
11011df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
11021df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
11031df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
11041df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
11051df7b17aSMarcel Holtmann 			amp_available = true;
11061df7b17aSMarcel Holtmann 			break;
11071df7b17aSMarcel Holtmann 		}
11081df7b17aSMarcel Holtmann 	}
11091df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
11101df7b17aSMarcel Holtmann 
11111df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
11121df7b17aSMarcel Holtmann 		return amp_available;
1113848566b3SMarcel Holtmann 
111493c3e8f5SAndrei Emeltchenko 	return false;
111593c3e8f5SAndrei Emeltchenko }
111693c3e8f5SAndrei Emeltchenko 
11175ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
11185ce66b59SAndrei Emeltchenko {
11195ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
11205ce66b59SAndrei Emeltchenko 	return true;
11215ce66b59SAndrei Emeltchenko }
11225ce66b59SAndrei Emeltchenko 
11232766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
11249b27f350SAndrei Emeltchenko {
11259b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
11269b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
11279b27f350SAndrei Emeltchenko 
11289b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
11299b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
11309b27f350SAndrei Emeltchenko 
11319b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
11329b27f350SAndrei Emeltchenko 
11339b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
11349b27f350SAndrei Emeltchenko 
11359b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
11369b27f350SAndrei Emeltchenko }
11379b27f350SAndrei Emeltchenko 
11388eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
11398eb200bdSMat Martineau {
11408eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
11418eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
11428eb200bdSMat Martineau 	req.psm  = chan->psm;
11438eb200bdSMat Martineau 	req.amp_id = amp_id;
11448eb200bdSMat Martineau 
11458eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
11468eb200bdSMat Martineau 
11478eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
11488eb200bdSMat Martineau 		       sizeof(req), &req);
11498eb200bdSMat Martineau }
11508eb200bdSMat Martineau 
115102b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
115202b0fbb9SMat Martineau {
115302b0fbb9SMat Martineau 	struct sk_buff *skb;
115402b0fbb9SMat Martineau 
115502b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
115602b0fbb9SMat Martineau 
115702b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
115802b0fbb9SMat Martineau 		return;
115902b0fbb9SMat Martineau 
116002b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
116102b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
116202b0fbb9SMat Martineau 	__clear_ack_timer(chan);
116302b0fbb9SMat Martineau 
116402b0fbb9SMat Martineau 	chan->retry_count = 0;
116502b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
116602b0fbb9SMat Martineau 		if (bt_cb(skb)->control.retries)
116702b0fbb9SMat Martineau 			bt_cb(skb)->control.retries = 1;
116802b0fbb9SMat Martineau 		else
116902b0fbb9SMat Martineau 			break;
117002b0fbb9SMat Martineau 	}
117102b0fbb9SMat Martineau 
117202b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
117302b0fbb9SMat Martineau 
117402b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
117502b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
117602b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
117702b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
117802b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
117902b0fbb9SMat Martineau 
118002b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
118102b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
118202b0fbb9SMat Martineau 
118302b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
118402b0fbb9SMat Martineau }
118502b0fbb9SMat Martineau 
11865f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
11875f3847a4SMat Martineau {
11885f3847a4SMat Martineau 	u8 move_role = chan->move_role;
11895f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
11905f3847a4SMat Martineau 
11915f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
11925f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
11935f3847a4SMat Martineau 
11945f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
11955f3847a4SMat Martineau 		return;
11965f3847a4SMat Martineau 
11975f3847a4SMat Martineau 	switch (move_role) {
11985f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
11995f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
12005f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
12015f3847a4SMat Martineau 		break;
12025f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
12035f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
12045f3847a4SMat Martineau 		break;
12055f3847a4SMat Martineau 	}
12065f3847a4SMat Martineau }
12075f3847a4SMat Martineau 
1208177f8f2bSJohan Hedberg static void l2cap_le_flowctl_start(struct l2cap_chan *chan)
1209177f8f2bSJohan Hedberg {
1210177f8f2bSJohan Hedberg 	chan->sdu = NULL;
1211177f8f2bSJohan Hedberg 	chan->sdu_last_frag = NULL;
1212177f8f2bSJohan Hedberg 	chan->sdu_len = 0;
1213177f8f2bSJohan Hedberg 
12143916aed8SJohan Hedberg 	if (chan->imtu < L2CAP_LE_DEFAULT_MPS)
12153916aed8SJohan Hedberg 		chan->mps = chan->imtu;
12163916aed8SJohan Hedberg 	else
12173916aed8SJohan Hedberg 		chan->mps = L2CAP_LE_DEFAULT_MPS;
12183916aed8SJohan Hedberg 
1219177f8f2bSJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
1220029727a3SJohan Hedberg 
1221029727a3SJohan Hedberg 	if (!chan->tx_credits)
1222029727a3SJohan Hedberg 		chan->ops->suspend(chan);
1223177f8f2bSJohan Hedberg }
1224177f8f2bSJohan Hedberg 
12259f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
12269f0caeb1SVinicius Costa Gomes {
12272827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
12289f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
12299f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
12309f0caeb1SVinicius Costa Gomes 
1231177f8f2bSJohan Hedberg 	if (chan->mode == L2CAP_MODE_LE_FLOWCTL)
1232177f8f2bSJohan Hedberg 		l2cap_le_flowctl_start(chan);
1233177f8f2bSJohan Hedberg 
123454a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
12359f0caeb1SVinicius Costa Gomes 
123654a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
12379f0caeb1SVinicius Costa Gomes }
12389f0caeb1SVinicius Costa Gomes 
1239f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1240f1496deeSJohan Hedberg {
1241f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1242f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1243f1496deeSJohan Hedberg 
1244595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1245595177f3SJohan Hedberg 		return;
1246595177f3SJohan Hedberg 
1247f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1248f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1249f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
12503916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
12510cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1252f1496deeSJohan Hedberg 
1253f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1254f1496deeSJohan Hedberg 
1255f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1256f1496deeSJohan Hedberg 		       sizeof(req), &req);
1257f1496deeSJohan Hedberg }
1258f1496deeSJohan Hedberg 
1259f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1260f1496deeSJohan Hedberg {
1261f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1262f1496deeSJohan Hedberg 
1263f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1264f1496deeSJohan Hedberg 		return;
1265f1496deeSJohan Hedberg 
1266f1496deeSJohan Hedberg 	if (!chan->psm) {
1267f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1268f1496deeSJohan Hedberg 		return;
1269f1496deeSJohan Hedberg 	}
1270f1496deeSJohan Hedberg 
1271f1496deeSJohan Hedberg 	if (chan->state == BT_CONNECT)
1272f1496deeSJohan Hedberg 		l2cap_le_connect(chan);
1273f1496deeSJohan Hedberg }
1274f1496deeSJohan Hedberg 
127593c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
127693c3e8f5SAndrei Emeltchenko {
127793c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
127893c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
127993c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1280f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1281f1496deeSJohan Hedberg 		l2cap_le_start(chan);
128293c3e8f5SAndrei Emeltchenko 	} else {
128393c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
128493c3e8f5SAndrei Emeltchenko 	}
128593c3e8f5SAndrei Emeltchenko }
128693c3e8f5SAndrei Emeltchenko 
1287fc7f8a7eSGustavo F. Padovan static void l2cap_do_start(struct l2cap_chan *chan)
12880a708f8fSGustavo F. Padovan {
12898c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
12900a708f8fSGustavo F. Padovan 
12919f0caeb1SVinicius Costa Gomes 	if (conn->hcon->type == LE_LINK) {
129296ac34fbSJohan Hedberg 		l2cap_le_start(chan);
12939f0caeb1SVinicius Costa Gomes 		return;
12949f0caeb1SVinicius Costa Gomes 	}
12959f0caeb1SVinicius Costa Gomes 
12960a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
12970a708f8fSGustavo F. Padovan 		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
12980a708f8fSGustavo F. Padovan 			return;
12990a708f8fSGustavo F. Padovan 
1300d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan) &&
130193c3e8f5SAndrei Emeltchenko 		    __l2cap_no_conn_pending(chan)) {
130293c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
130393c3e8f5SAndrei Emeltchenko 		}
13040a708f8fSGustavo F. Padovan 	} else {
13050a708f8fSGustavo F. Padovan 		struct l2cap_info_req req;
1306ac73498cSAndrei Emeltchenko 		req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
13070a708f8fSGustavo F. Padovan 
13080a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
13090a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
13100a708f8fSGustavo F. Padovan 
1311ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
13120a708f8fSGustavo F. Padovan 
13132d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
13142d792818SGustavo Padovan 			       sizeof(req), &req);
13150a708f8fSGustavo F. Padovan 	}
13160a708f8fSGustavo F. Padovan }
13170a708f8fSGustavo F. Padovan 
13180a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
13190a708f8fSGustavo F. Padovan {
13200a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
13210a708f8fSGustavo F. Padovan 	if (!disable_ertm)
13220a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
13230a708f8fSGustavo F. Padovan 
13240a708f8fSGustavo F. Padovan 	switch (mode) {
13250a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
13260a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
13270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
13280a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
13290a708f8fSGustavo F. Padovan 	default:
13300a708f8fSGustavo F. Padovan 		return 0x00;
13310a708f8fSGustavo F. Padovan 	}
13320a708f8fSGustavo F. Padovan }
13330a708f8fSGustavo F. Padovan 
13345e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
13350a708f8fSGustavo F. Padovan {
13365e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
13370a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
13380a708f8fSGustavo F. Padovan 
13390a708f8fSGustavo F. Padovan 	if (!conn)
13400a708f8fSGustavo F. Padovan 		return;
13410a708f8fSGustavo F. Padovan 
1342aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
13431a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
13441a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
13451a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
13460a708f8fSGustavo F. Padovan 	}
13470a708f8fSGustavo F. Padovan 
1348416fa752SAndrei Emeltchenko 	if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1349d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1350416fa752SAndrei Emeltchenko 		return;
1351416fa752SAndrei Emeltchenko 	}
1352416fa752SAndrei Emeltchenko 
1353fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1354fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
13552d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
13562d792818SGustavo Padovan 		       sizeof(req), &req);
13570a708f8fSGustavo F. Padovan 
1358f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
13590a708f8fSGustavo F. Padovan }
13600a708f8fSGustavo F. Padovan 
13610a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
13620a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
13630a708f8fSGustavo F. Padovan {
13643df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
13650a708f8fSGustavo F. Padovan 
13660a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
13670a708f8fSGustavo F. Padovan 
13683df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
13690a708f8fSGustavo F. Padovan 
13703df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
13716be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
13720a708f8fSGustavo F. Padovan 
1373715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
13746be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
13750a708f8fSGustavo F. Padovan 			continue;
13760a708f8fSGustavo F. Padovan 		}
13770a708f8fSGustavo F. Padovan 
137889bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1379d45fc423SGustavo F. Padovan 			if (!l2cap_chan_check_security(chan) ||
1380b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
13816be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13820a708f8fSGustavo F. Padovan 				continue;
13830a708f8fSGustavo F. Padovan 			}
13840a708f8fSGustavo F. Padovan 
1385c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1386c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1387c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
13880f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
13896be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
13900a708f8fSGustavo F. Padovan 				continue;
13910a708f8fSGustavo F. Padovan 			}
13920a708f8fSGustavo F. Padovan 
139393c3e8f5SAndrei Emeltchenko 			l2cap_start_connection(chan);
13940a708f8fSGustavo F. Padovan 
139589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
13960a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
13970a708f8fSGustavo F. Padovan 			char buf[128];
1398fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1399fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
14000a708f8fSGustavo F. Padovan 
1401d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan)) {
1402bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1403ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1404ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
14052dc4e510SGustavo Padovan 					chan->ops->defer(chan);
14060a708f8fSGustavo F. Padovan 
14070a708f8fSGustavo F. Padovan 				} else {
1408acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1409ac73498cSAndrei Emeltchenko 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
1410ac73498cSAndrei Emeltchenko 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
14110a708f8fSGustavo F. Padovan 				}
14120a708f8fSGustavo F. Padovan 			} else {
1413ac73498cSAndrei Emeltchenko 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
1414ac73498cSAndrei Emeltchenko 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
14150a708f8fSGustavo F. Padovan 			}
14160a708f8fSGustavo F. Padovan 
1417fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1418fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
14190a708f8fSGustavo F. Padovan 
1420c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
14210a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
14226be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
14230a708f8fSGustavo F. Padovan 				continue;
14240a708f8fSGustavo F. Padovan 			}
14250a708f8fSGustavo F. Padovan 
1426c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
14270a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
142873ffa904SGustavo F. Padovan 				       l2cap_build_conf_req(chan, buf), buf);
142973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
14300a708f8fSGustavo F. Padovan 		}
14310a708f8fSGustavo F. Padovan 
14326be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
14330a708f8fSGustavo F. Padovan 	}
14340a708f8fSGustavo F. Padovan 
14353df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
14360a708f8fSGustavo F. Padovan }
14370a708f8fSGustavo F. Padovan 
1438c2287681SIdo Yariv /* Find socket with cid and source/destination bdaddr.
1439b62f328bSVille Tervo  * Returns closest match, locked.
1440b62f328bSVille Tervo  */
1441d9b88702SAndrei Emeltchenko static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
1442c2287681SIdo Yariv 						    bdaddr_t *src,
1443c2287681SIdo Yariv 						    bdaddr_t *dst)
1444b62f328bSVille Tervo {
144523691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
1446b62f328bSVille Tervo 
144723691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
1448b62f328bSVille Tervo 
144923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
145089bc500eSGustavo F. Padovan 		if (state && c->state != state)
1451b62f328bSVille Tervo 			continue;
1452b62f328bSVille Tervo 
145323691d75SGustavo F. Padovan 		if (c->scid == cid) {
1454c2287681SIdo Yariv 			int src_match, dst_match;
1455c2287681SIdo Yariv 			int src_any, dst_any;
1456c2287681SIdo Yariv 
1457b62f328bSVille Tervo 			/* Exact match. */
14587eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
14597eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1460c2287681SIdo Yariv 			if (src_match && dst_match) {
146123691d75SGustavo F. Padovan 				read_unlock(&chan_list_lock);
146223691d75SGustavo F. Padovan 				return c;
146323691d75SGustavo F. Padovan 			}
1464b62f328bSVille Tervo 
1465b62f328bSVille Tervo 			/* Closest match */
14667eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
14677eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1468c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1469c2287681SIdo Yariv 			    (src_any && dst_any))
147023691d75SGustavo F. Padovan 				c1 = c;
1471b62f328bSVille Tervo 		}
1472b62f328bSVille Tervo 	}
1473280f294fSGustavo F. Padovan 
147423691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
1475b62f328bSVille Tervo 
147623691d75SGustavo F. Padovan 	return c1;
1477b62f328bSVille Tervo }
1478b62f328bSVille Tervo 
1479b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1480b62f328bSVille Tervo {
1481cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
148223691d75SGustavo F. Padovan 	struct l2cap_chan *chan, *pchan;
1483cc8dba2bSMarcel Holtmann 	u8 dst_type;
1484b62f328bSVille Tervo 
1485b62f328bSVille Tervo 	BT_DBG("");
1486b62f328bSVille Tervo 
1487b62f328bSVille Tervo 	/* Check if we have socket listening on cid */
1488073d1cf3SJohan Hedberg 	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
1489cc8dba2bSMarcel Holtmann 					  &hcon->src, &hcon->dst);
149023691d75SGustavo F. Padovan 	if (!pchan)
1491b62f328bSVille Tervo 		return;
1492b62f328bSVille Tervo 
149344f3b0fbSJohan Hedberg 	/* Client ATT sockets should override the server one */
149444f3b0fbSJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
149544f3b0fbSJohan Hedberg 		return;
149644f3b0fbSJohan Hedberg 
1497cc8dba2bSMarcel Holtmann 	dst_type = bdaddr_type(hcon, hcon->dst_type);
1498cc8dba2bSMarcel Holtmann 
1499cc8dba2bSMarcel Holtmann 	/* If device is blocked, do not create a channel for it */
1500cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
1501cc8dba2bSMarcel Holtmann 		return;
1502cc8dba2bSMarcel Holtmann 
15038ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
150462f3a2cfSGustavo F. Padovan 
150580b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
150680808e43SGustavo F. Padovan 	if (!chan)
1507b62f328bSVille Tervo 		goto clean;
1508b62f328bSVille Tervo 
15099f22398cSJohan Hedberg 	chan->dcid = L2CAP_CID_ATT;
15109f22398cSJohan Hedberg 
1511cc8dba2bSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
1512cc8dba2bSMarcel Holtmann 	bacpy(&chan->dst, &hcon->dst);
1513cc8dba2bSMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
1514cc8dba2bSMarcel Holtmann 	chan->dst_type = dst_type;
1515b62f328bSVille Tervo 
151644f3b0fbSJohan Hedberg 	__l2cap_chan_add(conn, chan);
151748454079SGustavo F. Padovan 
1518b62f328bSVille Tervo clean:
15198ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
1520b62f328bSVille Tervo }
1521b62f328bSVille Tervo 
15220a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
15230a708f8fSGustavo F. Padovan {
152448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1525cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
15260a708f8fSGustavo F. Padovan 
15270a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15280a708f8fSGustavo F. Padovan 
1529d8729922SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1530d8729922SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1531d8729922SJohan Hedberg 	 */
1532cc110922SVinicius Costa Gomes 	if (hcon->out && hcon->type == LE_LINK)
1533cc110922SVinicius Costa Gomes 		smp_conn_security(hcon, hcon->pending_sec_level);
1534160dc6acSVinicius Costa Gomes 
15353df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15360a708f8fSGustavo F. Padovan 
153744f3b0fbSJohan Hedberg 	if (hcon->type == LE_LINK)
153844f3b0fbSJohan Hedberg 		l2cap_le_conn_ready(conn);
153944f3b0fbSJohan Hedberg 
15403df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1541baa7e1faSGustavo F. Padovan 
15426be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
15430a708f8fSGustavo F. Padovan 
1544416fa752SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
1545416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1546416fa752SAndrei Emeltchenko 			continue;
1547416fa752SAndrei Emeltchenko 		}
1548416fa752SAndrei Emeltchenko 
1549cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1550f1496deeSJohan Hedberg 			l2cap_le_start(chan);
155163128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
155274e75740SGustavo Padovan 			l2cap_chan_ready(chan);
1553b501d6a1SAnderson Briglia 
15541c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1555fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
15561c244f79SGustavo Padovan 		}
15570a708f8fSGustavo F. Padovan 
15586be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
15590a708f8fSGustavo F. Padovan 	}
15600a708f8fSGustavo F. Padovan 
15613df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15620a708f8fSGustavo F. Padovan }
15630a708f8fSGustavo F. Padovan 
15640a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
15650a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
15660a708f8fSGustavo F. Padovan {
156748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
15680a708f8fSGustavo F. Padovan 
15690a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
15700a708f8fSGustavo F. Padovan 
15713df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
15720a708f8fSGustavo F. Padovan 
15733df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1574ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
15751d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
15760a708f8fSGustavo F. Padovan 	}
15770a708f8fSGustavo F. Padovan 
15783df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
15790a708f8fSGustavo F. Padovan }
15800a708f8fSGustavo F. Padovan 
1581f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
15820a708f8fSGustavo F. Padovan {
1583f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1584030013d8SGustavo F. Padovan 					       info_timer.work);
15850a708f8fSGustavo F. Padovan 
15860a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
15870a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
15880a708f8fSGustavo F. Padovan 
15890a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
15900a708f8fSGustavo F. Padovan }
15910a708f8fSGustavo F. Padovan 
15922c8e1411SDavid Herrmann /*
15932c8e1411SDavid Herrmann  * l2cap_user
15942c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
15952c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
15962c8e1411SDavid Herrmann  * during unregistration.
15972c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
15982c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
15992c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
16002c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
16012c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
16022c8e1411SDavid Herrmann  * any time if they don't.
16032c8e1411SDavid Herrmann  */
16042c8e1411SDavid Herrmann 
16052c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
16062c8e1411SDavid Herrmann {
16072c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16082c8e1411SDavid Herrmann 	int ret;
16092c8e1411SDavid Herrmann 
16102c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
16112c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
16122c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
16132c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
16142c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
16152c8e1411SDavid Herrmann 	 * here, too. */
16162c8e1411SDavid Herrmann 
16172c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16182c8e1411SDavid Herrmann 
16192c8e1411SDavid Herrmann 	if (user->list.next || user->list.prev) {
16202c8e1411SDavid Herrmann 		ret = -EINVAL;
16212c8e1411SDavid Herrmann 		goto out_unlock;
16222c8e1411SDavid Herrmann 	}
16232c8e1411SDavid Herrmann 
16242c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
16252c8e1411SDavid Herrmann 	if (!conn->hchan) {
16262c8e1411SDavid Herrmann 		ret = -ENODEV;
16272c8e1411SDavid Herrmann 		goto out_unlock;
16282c8e1411SDavid Herrmann 	}
16292c8e1411SDavid Herrmann 
16302c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
16312c8e1411SDavid Herrmann 	if (ret)
16322c8e1411SDavid Herrmann 		goto out_unlock;
16332c8e1411SDavid Herrmann 
16342c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
16352c8e1411SDavid Herrmann 	ret = 0;
16362c8e1411SDavid Herrmann 
16372c8e1411SDavid Herrmann out_unlock:
16382c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16392c8e1411SDavid Herrmann 	return ret;
16402c8e1411SDavid Herrmann }
16412c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
16422c8e1411SDavid Herrmann 
16432c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
16442c8e1411SDavid Herrmann {
16452c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
16462c8e1411SDavid Herrmann 
16472c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
16482c8e1411SDavid Herrmann 
16492c8e1411SDavid Herrmann 	if (!user->list.next || !user->list.prev)
16502c8e1411SDavid Herrmann 		goto out_unlock;
16512c8e1411SDavid Herrmann 
16522c8e1411SDavid Herrmann 	list_del(&user->list);
16532c8e1411SDavid Herrmann 	user->list.next = NULL;
16542c8e1411SDavid Herrmann 	user->list.prev = NULL;
16552c8e1411SDavid Herrmann 	user->remove(conn, user);
16562c8e1411SDavid Herrmann 
16572c8e1411SDavid Herrmann out_unlock:
16582c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
16592c8e1411SDavid Herrmann }
16602c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
16612c8e1411SDavid Herrmann 
16622c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
16632c8e1411SDavid Herrmann {
16642c8e1411SDavid Herrmann 	struct l2cap_user *user;
16652c8e1411SDavid Herrmann 
16662c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
16672c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
16682c8e1411SDavid Herrmann 		list_del(&user->list);
16692c8e1411SDavid Herrmann 		user->list.next = NULL;
16702c8e1411SDavid Herrmann 		user->list.prev = NULL;
16712c8e1411SDavid Herrmann 		user->remove(conn, user);
16722c8e1411SDavid Herrmann 	}
16732c8e1411SDavid Herrmann }
16742c8e1411SDavid Herrmann 
16755d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
16765d3de7dfSVinicius Costa Gomes {
16775d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
16785d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
16795d3de7dfSVinicius Costa Gomes 
16805d3de7dfSVinicius Costa Gomes 	if (!conn)
16815d3de7dfSVinicius Costa Gomes 		return;
16825d3de7dfSVinicius Costa Gomes 
16835d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
16845d3de7dfSVinicius Costa Gomes 
16855d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
16865d3de7dfSVinicius Costa Gomes 
16872c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
16882c8e1411SDavid Herrmann 
16893df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16903df91ea2SAndrei Emeltchenko 
16915d3de7dfSVinicius Costa Gomes 	/* Kill channels */
16925d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
169361d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
16946be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16956be36555SAndrei Emeltchenko 
16965d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
16976be36555SAndrei Emeltchenko 
16986be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16996be36555SAndrei Emeltchenko 
170080b98027SGustavo Padovan 		chan->ops->close(chan);
170161d6ef3eSMat Martineau 		l2cap_chan_put(chan);
17025d3de7dfSVinicius Costa Gomes 	}
17035d3de7dfSVinicius Costa Gomes 
17043df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17053df91ea2SAndrei Emeltchenko 
170673d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
170773d80debSLuiz Augusto von Dentz 
17085d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1709127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
17105d3de7dfSVinicius Costa Gomes 
171151a8efd7SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) {
1712127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->security_timer);
17138aab4757SVinicius Costa Gomes 		smp_chan_destroy(conn);
1714d26a2345SVinicius Costa Gomes 	}
17155d3de7dfSVinicius Costa Gomes 
17165d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
17179c903e37SDavid Herrmann 	conn->hchan = NULL;
17189c903e37SDavid Herrmann 	l2cap_conn_put(conn);
17195d3de7dfSVinicius Costa Gomes }
17205d3de7dfSVinicius Costa Gomes 
17216c9d42a1SGustavo F. Padovan static void security_timeout(struct work_struct *work)
17225d3de7dfSVinicius Costa Gomes {
17236c9d42a1SGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
17246c9d42a1SGustavo F. Padovan 					       security_timer.work);
17255d3de7dfSVinicius Costa Gomes 
1726d06cc416SJohan Hedberg 	BT_DBG("conn %p", conn);
1727d06cc416SJohan Hedberg 
1728d06cc416SJohan Hedberg 	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
1729d06cc416SJohan Hedberg 		smp_chan_destroy(conn);
17305d3de7dfSVinicius Costa Gomes 		l2cap_conn_del(conn->hcon, ETIMEDOUT);
17315d3de7dfSVinicius Costa Gomes 	}
1732d06cc416SJohan Hedberg }
17335d3de7dfSVinicius Costa Gomes 
1734baf43251SClaudio Takahasi static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
17350a708f8fSGustavo F. Padovan {
17360a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
173773d80debSLuiz Augusto von Dentz 	struct hci_chan *hchan;
17380a708f8fSGustavo F. Padovan 
1739baf43251SClaudio Takahasi 	if (conn)
17400a708f8fSGustavo F. Padovan 		return conn;
17410a708f8fSGustavo F. Padovan 
174273d80debSLuiz Augusto von Dentz 	hchan = hci_chan_create(hcon);
174373d80debSLuiz Augusto von Dentz 	if (!hchan)
17440a708f8fSGustavo F. Padovan 		return NULL;
17450a708f8fSGustavo F. Padovan 
17468bcde1f2SGustavo Padovan 	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
174773d80debSLuiz Augusto von Dentz 	if (!conn) {
174873d80debSLuiz Augusto von Dentz 		hci_chan_del(hchan);
174973d80debSLuiz Augusto von Dentz 		return NULL;
175073d80debSLuiz Augusto von Dentz 	}
175173d80debSLuiz Augusto von Dentz 
17529c903e37SDavid Herrmann 	kref_init(&conn->ref);
17530a708f8fSGustavo F. Padovan 	hcon->l2cap_data = conn;
17540a708f8fSGustavo F. Padovan 	conn->hcon = hcon;
17559c903e37SDavid Herrmann 	hci_conn_get(conn->hcon);
175673d80debSLuiz Augusto von Dentz 	conn->hchan = hchan;
17570a708f8fSGustavo F. Padovan 
175873d80debSLuiz Augusto von Dentz 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
17590a708f8fSGustavo F. Padovan 
1760dcc042d5SAndrei Emeltchenko 	switch (hcon->type) {
1761dcc042d5SAndrei Emeltchenko 	case LE_LINK:
1762dcc042d5SAndrei Emeltchenko 		if (hcon->hdev->le_mtu) {
1763acd7d370SVille Tervo 			conn->mtu = hcon->hdev->le_mtu;
1764dcc042d5SAndrei Emeltchenko 			break;
1765dcc042d5SAndrei Emeltchenko 		}
1766dcc042d5SAndrei Emeltchenko 		/* fall through */
1767dcc042d5SAndrei Emeltchenko 	default:
17680a708f8fSGustavo F. Padovan 		conn->mtu = hcon->hdev->acl_mtu;
1769dcc042d5SAndrei Emeltchenko 		break;
1770dcc042d5SAndrei Emeltchenko 	}
1771acd7d370SVille Tervo 
17720a708f8fSGustavo F. Padovan 	conn->feat_mask = 0;
17730a708f8fSGustavo F. Padovan 
1774848566b3SMarcel Holtmann 	if (hcon->type == ACL_LINK)
1775848566b3SMarcel Holtmann 		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
1776848566b3SMarcel Holtmann 					    &hcon->hdev->dev_flags);
1777848566b3SMarcel Holtmann 
17780a708f8fSGustavo F. Padovan 	spin_lock_init(&conn->lock);
17793df91ea2SAndrei Emeltchenko 	mutex_init(&conn->chan_lock);
1780baa7e1faSGustavo F. Padovan 
1781baa7e1faSGustavo F. Padovan 	INIT_LIST_HEAD(&conn->chan_l);
17822c8e1411SDavid Herrmann 	INIT_LIST_HEAD(&conn->users);
17830a708f8fSGustavo F. Padovan 
17845d3de7dfSVinicius Costa Gomes 	if (hcon->type == LE_LINK)
17856c9d42a1SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
17865d3de7dfSVinicius Costa Gomes 	else
1787030013d8SGustavo F. Padovan 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
17880a708f8fSGustavo F. Padovan 
17899f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
17900a708f8fSGustavo F. Padovan 
17910a708f8fSGustavo F. Padovan 	return conn;
17920a708f8fSGustavo F. Padovan }
17930a708f8fSGustavo F. Padovan 
17949c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
17959c903e37SDavid Herrmann {
17969c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
17979c903e37SDavid Herrmann 
17989c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
17999c903e37SDavid Herrmann 	kfree(conn);
18009c903e37SDavid Herrmann }
18019c903e37SDavid Herrmann 
18029c903e37SDavid Herrmann void l2cap_conn_get(struct l2cap_conn *conn)
18039c903e37SDavid Herrmann {
18049c903e37SDavid Herrmann 	kref_get(&conn->ref);
18059c903e37SDavid Herrmann }
18069c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
18079c903e37SDavid Herrmann 
18089c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
18099c903e37SDavid Herrmann {
18109c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
18119c903e37SDavid Herrmann }
18129c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
18139c903e37SDavid Herrmann 
18140a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
18150a708f8fSGustavo F. Padovan 
1816c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
18170a708f8fSGustavo F. Padovan  * Returns closest match.
18180a708f8fSGustavo F. Padovan  */
1819c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1820c2287681SIdo Yariv 						   bdaddr_t *src,
1821bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1822bf20fd4eSJohan Hedberg 						   u8 link_type)
18230a708f8fSGustavo F. Padovan {
182423691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
18250a708f8fSGustavo F. Padovan 
182623691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
18270a708f8fSGustavo F. Padovan 
182823691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
182989bc500eSGustavo F. Padovan 		if (state && c->state != state)
18300a708f8fSGustavo F. Padovan 			continue;
18310a708f8fSGustavo F. Padovan 
1832bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1833bf20fd4eSJohan Hedberg 			continue;
1834bf20fd4eSJohan Hedberg 
1835bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1836bf20fd4eSJohan Hedberg 			continue;
1837bf20fd4eSJohan Hedberg 
183823691d75SGustavo F. Padovan 		if (c->psm == psm) {
1839c2287681SIdo Yariv 			int src_match, dst_match;
1840c2287681SIdo Yariv 			int src_any, dst_any;
1841c2287681SIdo Yariv 
18420a708f8fSGustavo F. Padovan 			/* Exact match. */
18437eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
18447eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1845c2287681SIdo Yariv 			if (src_match && dst_match) {
1846a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
184723691d75SGustavo F. Padovan 				return c;
184823691d75SGustavo F. Padovan 			}
18490a708f8fSGustavo F. Padovan 
18500a708f8fSGustavo F. Padovan 			/* Closest match */
18517eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
18527eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1853c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1854c2287681SIdo Yariv 			    (src_any && dst_any))
185523691d75SGustavo F. Padovan 				c1 = c;
18560a708f8fSGustavo F. Padovan 		}
18570a708f8fSGustavo F. Padovan 	}
18580a708f8fSGustavo F. Padovan 
185923691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
18600a708f8fSGustavo F. Padovan 
186123691d75SGustavo F. Padovan 	return c1;
18620a708f8fSGustavo F. Padovan }
18630a708f8fSGustavo F. Padovan 
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 
188403a00194SGustavo F. Padovan 	/* PSM must be odd and lsb of upper byte must be 0 */
188503a00194SGustavo F. Padovan 	if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
188603a00194SGustavo F. Padovan 	    chan->chan_type != L2CAP_CHAN_RAW) {
188703a00194SGustavo F. Padovan 		err = -EINVAL;
188803a00194SGustavo F. Padovan 		goto done;
188903a00194SGustavo F. Padovan 	}
189003a00194SGustavo F. Padovan 
189103a00194SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
189203a00194SGustavo F. Padovan 		err = -EINVAL;
189303a00194SGustavo F. Padovan 		goto done;
189403a00194SGustavo F. Padovan 	}
189503a00194SGustavo F. Padovan 
189603a00194SGustavo F. Padovan 	switch (chan->mode) {
189703a00194SGustavo F. Padovan 	case L2CAP_MODE_BASIC:
189838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
189903a00194SGustavo F. Padovan 		break;
190003a00194SGustavo F. Padovan 	case L2CAP_MODE_ERTM:
190103a00194SGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
190203a00194SGustavo F. Padovan 		if (!disable_ertm)
190303a00194SGustavo F. Padovan 			break;
190403a00194SGustavo F. Padovan 		/* fall through */
190503a00194SGustavo F. Padovan 	default:
190603a00194SGustavo F. Padovan 		err = -ENOTSUPP;
190703a00194SGustavo F. Padovan 		goto done;
190803a00194SGustavo F. Padovan 	}
190903a00194SGustavo F. Padovan 
19100797e01dSGustavo Padovan 	switch (chan->state) {
191103a00194SGustavo F. Padovan 	case BT_CONNECT:
191203a00194SGustavo F. Padovan 	case BT_CONNECT2:
191303a00194SGustavo F. Padovan 	case BT_CONFIG:
191403a00194SGustavo F. Padovan 		/* Already connecting */
191503a00194SGustavo F. Padovan 		err = 0;
191603a00194SGustavo F. Padovan 		goto done;
191703a00194SGustavo F. Padovan 
191803a00194SGustavo F. Padovan 	case BT_CONNECTED:
191903a00194SGustavo F. Padovan 		/* Already connected */
192003a00194SGustavo F. Padovan 		err = -EISCONN;
192103a00194SGustavo F. Padovan 		goto done;
192203a00194SGustavo F. Padovan 
192303a00194SGustavo F. Padovan 	case BT_OPEN:
192403a00194SGustavo F. Padovan 	case BT_BOUND:
192503a00194SGustavo F. Padovan 		/* Can connect */
192603a00194SGustavo F. Padovan 		break;
192703a00194SGustavo F. Padovan 
192803a00194SGustavo F. Padovan 	default:
192903a00194SGustavo F. Padovan 		err = -EBADFD;
193003a00194SGustavo F. Padovan 		goto done;
193103a00194SGustavo F. Padovan 	}
193203a00194SGustavo F. Padovan 
193303a00194SGustavo F. Padovan 	/* Set destination address and psm */
19347eafc59eSMarcel Holtmann 	bacpy(&chan->dst, dst);
19354f1654e0SMarcel Holtmann 	chan->dst_type = dst_type;
19366be36555SAndrei Emeltchenko 
193703a00194SGustavo F. Padovan 	chan->psm = psm;
193803a00194SGustavo F. Padovan 	chan->dcid = cid;
19390a708f8fSGustavo F. Padovan 
19404343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
19410a708f8fSGustavo F. Padovan 
1942f224ca5fSJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
19438e9f9892SAndre Guedes 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
19444343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1945acd7d370SVille Tervo 	else
19468e9f9892SAndre Guedes 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
19474343478fSGustavo F. Padovan 				   chan->sec_level, auth_type);
1948acd7d370SVille Tervo 
194930e76272SVille Tervo 	if (IS_ERR(hcon)) {
195030e76272SVille Tervo 		err = PTR_ERR(hcon);
19510a708f8fSGustavo F. Padovan 		goto done;
195230e76272SVille Tervo 	}
19530a708f8fSGustavo F. Padovan 
1954baf43251SClaudio Takahasi 	conn = l2cap_conn_add(hcon);
19550a708f8fSGustavo F. Padovan 	if (!conn) {
195676a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
195730e76272SVille Tervo 		err = -ENOMEM;
19580a708f8fSGustavo F. Padovan 		goto done;
19590a708f8fSGustavo F. Padovan 	}
19600a708f8fSGustavo F. Padovan 
1961141d5706SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
196276a68ba0SDavid Herrmann 		hci_conn_drop(hcon);
1963141d5706SJohan Hedberg 		err = -EBUSY;
19649f0caeb1SVinicius Costa Gomes 		goto done;
19659f0caeb1SVinicius Costa Gomes 	}
19669f0caeb1SVinicius Costa Gomes 
19670a708f8fSGustavo F. Padovan 	/* Update source addr of the socket */
19687eafc59eSMarcel Holtmann 	bacpy(&chan->src, &hcon->src);
19694f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
19700a708f8fSGustavo F. Padovan 
19716be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
197248454079SGustavo F. Padovan 	l2cap_chan_add(conn, chan);
19736be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
197448454079SGustavo F. Padovan 
19755ee9891dSJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
19765ee9891dSJohan Hedberg 	hci_conn_drop(hcon);
19775ee9891dSJohan Hedberg 
19786be36555SAndrei Emeltchenko 	l2cap_state_change(chan, BT_CONNECT);
19798d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
19800a708f8fSGustavo F. Padovan 
19810a708f8fSGustavo F. Padovan 	if (hcon->state == BT_CONNECTED) {
1982715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1983c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
1984d45fc423SGustavo F. Padovan 			if (l2cap_chan_check_security(chan))
19856be36555SAndrei Emeltchenko 				l2cap_state_change(chan, BT_CONNECTED);
19860a708f8fSGustavo F. Padovan 		} else
1987fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
19880a708f8fSGustavo F. Padovan 	}
19890a708f8fSGustavo F. Padovan 
199030e76272SVille Tervo 	err = 0;
199130e76272SVille Tervo 
19920a708f8fSGustavo F. Padovan done:
19936be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
199409fd0de5SGustavo F. Padovan 	hci_dev_unlock(hdev);
19950a708f8fSGustavo F. Padovan 	hci_dev_put(hdev);
19960a708f8fSGustavo F. Padovan 	return err;
19970a708f8fSGustavo F. Padovan }
19980a708f8fSGustavo F. Padovan 
1999721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
20000a708f8fSGustavo F. Padovan {
2001721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2002721c4181SGustavo F. Padovan 					       monitor_timer.work);
20030a708f8fSGustavo F. Padovan 
2004525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
20050a708f8fSGustavo F. Padovan 
20066be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20076be36555SAndrei Emeltchenko 
200880909e04SMat Martineau 	if (!chan->conn) {
20096be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
20108d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
20110a708f8fSGustavo F. Padovan 		return;
20120a708f8fSGustavo F. Padovan 	}
20130a708f8fSGustavo F. Padovan 
2014401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
20150a708f8fSGustavo F. Padovan 
20166be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20178d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20180a708f8fSGustavo F. Padovan }
20190a708f8fSGustavo F. Padovan 
2020721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20210a708f8fSGustavo F. Padovan {
2022721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2023721c4181SGustavo F. Padovan 					       retrans_timer.work);
20240a708f8fSGustavo F. Padovan 
202549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20260a708f8fSGustavo F. Padovan 
20276be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20286be36555SAndrei Emeltchenko 
202980909e04SMat Martineau 	if (!chan->conn) {
203080909e04SMat Martineau 		l2cap_chan_unlock(chan);
203180909e04SMat Martineau 		l2cap_chan_put(chan);
203280909e04SMat Martineau 		return;
203380909e04SMat Martineau 	}
20340a708f8fSGustavo F. Padovan 
2035401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20366be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20378d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20380a708f8fSGustavo F. Padovan }
20390a708f8fSGustavo F. Padovan 
2040d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20413733937dSMat Martineau 				 struct sk_buff_head *skbs)
20420a708f8fSGustavo F. Padovan {
20430a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20443733937dSMat Martineau 	struct l2cap_ctrl *control;
20450a708f8fSGustavo F. Padovan 
20463733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20473733937dSMat Martineau 
2048b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2049b99e13adSMat Martineau 		return;
2050b99e13adSMat Martineau 
20513733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20523733937dSMat Martineau 
20533733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20543733937dSMat Martineau 
20553733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20563733937dSMat Martineau 
20573733937dSMat Martineau 		bt_cb(skb)->control.retries = 1;
20583733937dSMat Martineau 		control = &bt_cb(skb)->control;
20593733937dSMat Martineau 
20603733937dSMat Martineau 		control->reqseq = 0;
20613733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20623733937dSMat Martineau 
20633733937dSMat Martineau 		__pack_control(chan, control, skb);
20640a708f8fSGustavo F. Padovan 
206547d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20663733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20673733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20680a708f8fSGustavo F. Padovan 		}
20690a708f8fSGustavo F. Padovan 
20704343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20710a708f8fSGustavo F. Padovan 
2072b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20733733937dSMat Martineau 
2074836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20753733937dSMat Martineau 		chan->frames_sent++;
20760a708f8fSGustavo F. Padovan 	}
20770a708f8fSGustavo F. Padovan }
20780a708f8fSGustavo F. Padovan 
207967c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20800a708f8fSGustavo F. Padovan {
20810a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
208218a48e76SMat Martineau 	struct l2cap_ctrl *control;
208318a48e76SMat Martineau 	int sent = 0;
208418a48e76SMat Martineau 
208518a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20860a708f8fSGustavo F. Padovan 
208789bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20880a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20890a708f8fSGustavo F. Padovan 
209094122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
209194122bbeSMat Martineau 		return 0;
209294122bbeSMat Martineau 
2093b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2094b99e13adSMat Martineau 		return 0;
2095b99e13adSMat Martineau 
209618a48e76SMat Martineau 	while (chan->tx_send_head &&
209718a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
209818a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
20990a708f8fSGustavo F. Padovan 
210018a48e76SMat Martineau 		skb = chan->tx_send_head;
21010a708f8fSGustavo F. Padovan 
210218a48e76SMat Martineau 		bt_cb(skb)->control.retries = 1;
210318a48e76SMat Martineau 		control = &bt_cb(skb)->control;
21040a708f8fSGustavo F. Padovan 
2105e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
210618a48e76SMat Martineau 			control->final = 1;
2107e2ab4353SGustavo F. Padovan 
210818a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
210918a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
211018a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
21110a708f8fSGustavo F. Padovan 
211218a48e76SMat Martineau 		__pack_control(chan, control, skb);
21130a708f8fSGustavo F. Padovan 
211447d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
211518a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
211618a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
21170a708f8fSGustavo F. Padovan 		}
21180a708f8fSGustavo F. Padovan 
211918a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
212018a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
212118a48e76SMat Martineau 		 */
212218a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
212318a48e76SMat Martineau 
212418a48e76SMat Martineau 		if (!tx_skb)
212518a48e76SMat Martineau 			break;
21260a708f8fSGustavo F. Padovan 
21271a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21280a708f8fSGustavo F. Padovan 
2129836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21306a026610SGustavo F. Padovan 		chan->unacked_frames++;
21316a026610SGustavo F. Padovan 		chan->frames_sent++;
213218a48e76SMat Martineau 		sent++;
21330a708f8fSGustavo F. Padovan 
213458d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
213558d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21360a708f8fSGustavo F. Padovan 		else
213758d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
213818a48e76SMat Martineau 
213918a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2140b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21410a708f8fSGustavo F. Padovan 	}
21420a708f8fSGustavo F. Padovan 
2143b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2144b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
214518a48e76SMat Martineau 
214618a48e76SMat Martineau 	return sent;
21470a708f8fSGustavo F. Padovan }
21480a708f8fSGustavo F. Padovan 
2149e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2150e1fbd4c1SMat Martineau {
2151e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2152e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2153e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2154e1fbd4c1SMat Martineau 	u16 seq;
2155e1fbd4c1SMat Martineau 
2156e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2157e1fbd4c1SMat Martineau 
2158e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2159e1fbd4c1SMat Martineau 		return;
2160e1fbd4c1SMat Martineau 
2161b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2162b99e13adSMat Martineau 		return;
2163b99e13adSMat Martineau 
2164e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2165e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2166e1fbd4c1SMat Martineau 
2167e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2168e1fbd4c1SMat Martineau 		if (!skb) {
2169e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2170e1fbd4c1SMat Martineau 			       seq);
2171e1fbd4c1SMat Martineau 			continue;
2172e1fbd4c1SMat Martineau 		}
2173e1fbd4c1SMat Martineau 
2174e1fbd4c1SMat Martineau 		bt_cb(skb)->control.retries++;
2175e1fbd4c1SMat Martineau 		control = bt_cb(skb)->control;
2176e1fbd4c1SMat Martineau 
2177e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2178e1fbd4c1SMat Martineau 		    bt_cb(skb)->control.retries > chan->max_tx) {
2179e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21805e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2181e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2182e1fbd4c1SMat Martineau 			break;
2183e1fbd4c1SMat Martineau 		}
2184e1fbd4c1SMat Martineau 
2185e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2186e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2187e1fbd4c1SMat Martineau 			control.final = 1;
2188e1fbd4c1SMat Martineau 		else
2189e1fbd4c1SMat Martineau 			control.final = 0;
2190e1fbd4c1SMat Martineau 
2191e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2192e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2193e1fbd4c1SMat Martineau 			 * writeable copy
2194e1fbd4c1SMat Martineau 			 */
21958bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2196e1fbd4c1SMat Martineau 		} else {
21978bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2198e1fbd4c1SMat Martineau 		}
2199e1fbd4c1SMat Martineau 
2200e1fbd4c1SMat Martineau 		if (!tx_skb) {
2201e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2202e1fbd4c1SMat Martineau 			break;
2203e1fbd4c1SMat Martineau 		}
2204e1fbd4c1SMat Martineau 
2205e1fbd4c1SMat Martineau 		/* Update skb contents */
2206e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2207e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2208e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2209e1fbd4c1SMat Martineau 		} else {
2210e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2211e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2212e1fbd4c1SMat Martineau 		}
2213e1fbd4c1SMat Martineau 
2214e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
2215e1fbd4c1SMat Martineau 			u16 fcs = crc16(0, (u8 *) tx_skb->data, tx_skb->len);
2216e1fbd4c1SMat Martineau 			put_unaligned_le16(fcs, skb_put(tx_skb,
2217e1fbd4c1SMat Martineau 							L2CAP_FCS_SIZE));
2218e1fbd4c1SMat Martineau 		}
2219e1fbd4c1SMat Martineau 
2220e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2221e1fbd4c1SMat Martineau 
2222e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2223e1fbd4c1SMat Martineau 
2224e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2225e1fbd4c1SMat Martineau 	}
2226e1fbd4c1SMat Martineau }
2227e1fbd4c1SMat Martineau 
2228f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2229f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2230f80842a8SMat Martineau {
2231f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2232f80842a8SMat Martineau 
2233f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2234f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2235f80842a8SMat Martineau }
2236f80842a8SMat Martineau 
2237d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2238d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2239d2a7ac5dSMat Martineau {
2240e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2241e1fbd4c1SMat Martineau 
2242e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2243e1fbd4c1SMat Martineau 
2244e1fbd4c1SMat Martineau 	if (control->poll)
2245e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2246e1fbd4c1SMat Martineau 
2247e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2248e1fbd4c1SMat Martineau 
2249e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2250e1fbd4c1SMat Martineau 		return;
2251e1fbd4c1SMat Martineau 
2252e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2253e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2254e1fbd4c1SMat Martineau 			if (bt_cb(skb)->control.txseq == control->reqseq ||
2255e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2256e1fbd4c1SMat Martineau 				break;
2257e1fbd4c1SMat Martineau 		}
2258e1fbd4c1SMat Martineau 
2259e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2260e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2261e1fbd4c1SMat Martineau 				break;
2262e1fbd4c1SMat Martineau 
2263e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2264e1fbd4c1SMat Martineau 					      bt_cb(skb)->control.txseq);
2265e1fbd4c1SMat Martineau 		}
2266e1fbd4c1SMat Martineau 
2267e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2268e1fbd4c1SMat Martineau 	}
2269d2a7ac5dSMat Martineau }
2270d2a7ac5dSMat Martineau 
2271b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2272b17e73bbSSzymon Janc {
22730a0aba42SMat Martineau 	struct l2cap_ctrl control;
22740a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22750a0aba42SMat Martineau 					 chan->last_acked_seq);
22760a0aba42SMat Martineau 	int threshold;
22770a0aba42SMat Martineau 
22780a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22790a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22800a0aba42SMat Martineau 
22810a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22820a0aba42SMat Martineau 	control.sframe = 1;
22830a0aba42SMat Martineau 
22840a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22850a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2286b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22870a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22880a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22890a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22900a0aba42SMat Martineau 	} else {
22910a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22920a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22930a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22940a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22950a0aba42SMat Martineau 				frames_to_ack = 0;
22960a0aba42SMat Martineau 		}
22970a0aba42SMat Martineau 
2298c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
22990a0aba42SMat Martineau 		 * Calculate without mul or div
23000a0aba42SMat Martineau 		 */
2301c20f8e35SMat Martineau 		threshold = chan->ack_win;
23020a0aba42SMat Martineau 		threshold += threshold << 1;
23030a0aba42SMat Martineau 		threshold >>= 2;
23040a0aba42SMat Martineau 
2305b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
23060a0aba42SMat Martineau 		       threshold);
23070a0aba42SMat Martineau 
23080a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
23090a0aba42SMat Martineau 			__clear_ack_timer(chan);
23100a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
23110a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
23120a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
23130a0aba42SMat Martineau 			frames_to_ack = 0;
23140a0aba42SMat Martineau 		}
23150a0aba42SMat Martineau 
23160a0aba42SMat Martineau 		if (frames_to_ack)
23170a0aba42SMat Martineau 			__set_ack_timer(chan);
23180a0aba42SMat Martineau 	}
2319b17e73bbSSzymon Janc }
2320b17e73bbSSzymon Janc 
232104124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
232204124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
232304124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23240a708f8fSGustavo F. Padovan {
23250952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23260a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
232790338947SGustavo Padovan 	int sent = 0;
23280a708f8fSGustavo F. Padovan 
23290a708f8fSGustavo F. Padovan 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
23300a708f8fSGustavo F. Padovan 		return -EFAULT;
23310a708f8fSGustavo F. Padovan 
23320a708f8fSGustavo F. Padovan 	sent += count;
23330a708f8fSGustavo F. Padovan 	len  -= count;
23340a708f8fSGustavo F. Padovan 
23350a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23360a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23370a708f8fSGustavo F. Padovan 	while (len) {
2338fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2339fbe00700SGustavo Padovan 
23400a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23410a708f8fSGustavo F. Padovan 
2342fbe00700SGustavo Padovan 		tmp = chan->ops->alloc_skb(chan, count,
234390338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2344fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2345fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23462f7719ceSAndrei Emeltchenko 
2347fbe00700SGustavo Padovan 		*frag = tmp;
2348fbe00700SGustavo Padovan 
23490a708f8fSGustavo F. Padovan 		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
23500a708f8fSGustavo F. Padovan 			return -EFAULT;
23510a708f8fSGustavo F. Padovan 
23525e59b791SLuiz Augusto von Dentz 		(*frag)->priority = skb->priority;
23535e59b791SLuiz Augusto von Dentz 
23540a708f8fSGustavo F. Padovan 		sent += count;
23550a708f8fSGustavo F. Padovan 		len  -= count;
23560a708f8fSGustavo F. Padovan 
23572d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23582d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23592d0ed3d5SGustavo Padovan 
23600a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23610a708f8fSGustavo F. Padovan 	}
23620a708f8fSGustavo F. Padovan 
23630a708f8fSGustavo F. Padovan 	return sent;
23640a708f8fSGustavo F. Padovan }
23650a708f8fSGustavo F. Padovan 
23665e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23675e59b791SLuiz Augusto von Dentz 						 struct msghdr *msg, size_t len,
23685e59b791SLuiz Augusto von Dentz 						 u32 priority)
23690a708f8fSGustavo F. Padovan {
23708c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23710a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
237203a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23730a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23740a708f8fSGustavo F. Padovan 
237543b1b8dfSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan,
237643b1b8dfSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len, priority);
23770a708f8fSGustavo F. Padovan 
23780a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23792f7719ceSAndrei Emeltchenko 
23802f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
238190338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
238290338947SGustavo Padovan 	if (IS_ERR(skb))
238390338947SGustavo Padovan 		return skb;
23840a708f8fSGustavo F. Padovan 
23855e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
23865e59b791SLuiz Augusto von Dentz 
23870a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23880a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2389fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2390daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
239143b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23920a708f8fSGustavo F. Padovan 
23930952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23940a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23950a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23960a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23970a708f8fSGustavo F. Padovan 	}
23980a708f8fSGustavo F. Padovan 	return skb;
23990a708f8fSGustavo F. Padovan }
24000a708f8fSGustavo F. Padovan 
24015e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
24025e59b791SLuiz Augusto von Dentz 					      struct msghdr *msg, size_t len,
24035e59b791SLuiz Augusto von Dentz 					      u32 priority)
24040a708f8fSGustavo F. Padovan {
24058c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24060a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2407f2ba7faeSGustavo Padovan 	int err, count;
24080a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24090a708f8fSGustavo F. Padovan 
2410b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24110a708f8fSGustavo F. Padovan 
2412f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
24132f7719ceSAndrei Emeltchenko 
2414f2ba7faeSGustavo Padovan 	skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE,
241590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
241690338947SGustavo Padovan 	if (IS_ERR(skb))
241790338947SGustavo Padovan 		return skb;
24180a708f8fSGustavo F. Padovan 
24195e59b791SLuiz Augusto von Dentz 	skb->priority = priority;
24205e59b791SLuiz Augusto von Dentz 
24210a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24220a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2423fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24246ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24250a708f8fSGustavo F. Padovan 
24260952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24270a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24280a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24290a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24300a708f8fSGustavo F. Padovan 	}
24310a708f8fSGustavo F. Padovan 	return skb;
24320a708f8fSGustavo F. Padovan }
24330a708f8fSGustavo F. Padovan 
2434ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2435ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
243694122bbeSMat Martineau 					       u16 sdulen)
24370a708f8fSGustavo F. Padovan {
24388c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24390a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2440e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24410a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24420a708f8fSGustavo F. Padovan 
2443b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24440a708f8fSGustavo F. Padovan 
24450a708f8fSGustavo F. Padovan 	if (!conn)
24460a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24470a708f8fSGustavo F. Padovan 
2448ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2449e4ca6d98SAndrei Emeltchenko 
24500a708f8fSGustavo F. Padovan 	if (sdulen)
245103a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24520a708f8fSGustavo F. Padovan 
245347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
245403a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24550a708f8fSGustavo F. Padovan 
24560a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24572f7719ceSAndrei Emeltchenko 
24582f7719ceSAndrei Emeltchenko 	skb = chan->ops->alloc_skb(chan, count + hlen,
245990338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
246090338947SGustavo Padovan 	if (IS_ERR(skb))
246190338947SGustavo Padovan 		return skb;
24620a708f8fSGustavo F. Padovan 
24630a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24640a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2465fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24660a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
246788843ab0SAndrei Emeltchenko 
246818a48e76SMat Martineau 	/* Control header is populated later */
246918a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
247018a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
247118a48e76SMat Martineau 	else
247218a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
247388843ab0SAndrei Emeltchenko 
24740a708f8fSGustavo F. Padovan 	if (sdulen)
247503a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24760a708f8fSGustavo F. Padovan 
24770952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24780a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24790a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24800a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24810a708f8fSGustavo F. Padovan 	}
24820a708f8fSGustavo F. Padovan 
248318a48e76SMat Martineau 	bt_cb(skb)->control.fcs = chan->fcs;
24843ce3514fSMat Martineau 	bt_cb(skb)->control.retries = 0;
24850a708f8fSGustavo F. Padovan 	return skb;
24860a708f8fSGustavo F. Padovan }
24870a708f8fSGustavo F. Padovan 
248894122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
248994122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
249094122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24910a708f8fSGustavo F. Padovan {
24920a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
249394122bbeSMat Martineau 	u16 sdu_len;
249494122bbeSMat Martineau 	size_t pdu_len;
249594122bbeSMat Martineau 	u8 sar;
24960a708f8fSGustavo F. Padovan 
2497b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24980a708f8fSGustavo F. Padovan 
249994122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
250094122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
250194122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
250294122bbeSMat Martineau 	 */
250394122bbeSMat Martineau 
250494122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
250594122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
250694122bbeSMat Martineau 
2507a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2508a549574dSMat Martineau 	if (!chan->hs_hcon)
250994122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
251094122bbeSMat Martineau 
251194122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
251235d401dfSGustavo Padovan 	if (chan->fcs)
251335d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
251435d401dfSGustavo Padovan 
2515ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
251694122bbeSMat Martineau 
251794122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
251894122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
251994122bbeSMat Martineau 
252094122bbeSMat Martineau 	if (len <= pdu_len) {
252194122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
252294122bbeSMat Martineau 		sdu_len = 0;
252394122bbeSMat Martineau 		pdu_len = len;
252494122bbeSMat Martineau 	} else {
252594122bbeSMat Martineau 		sar = L2CAP_SAR_START;
252694122bbeSMat Martineau 		sdu_len = len;
252794122bbeSMat Martineau 		pdu_len -= L2CAP_SDULEN_SIZE;
252894122bbeSMat Martineau 	}
25290a708f8fSGustavo F. Padovan 
25300a708f8fSGustavo F. Padovan 	while (len > 0) {
253194122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25320a708f8fSGustavo F. Padovan 
25330a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
253494122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25350a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25360a708f8fSGustavo F. Padovan 		}
25370a708f8fSGustavo F. Padovan 
253894122bbeSMat Martineau 		bt_cb(skb)->control.sar = sar;
253994122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25400a708f8fSGustavo F. Padovan 
254194122bbeSMat Martineau 		len -= pdu_len;
254294122bbeSMat Martineau 		if (sdu_len) {
254394122bbeSMat Martineau 			sdu_len = 0;
254494122bbeSMat Martineau 			pdu_len += L2CAP_SDULEN_SIZE;
254594122bbeSMat Martineau 		}
254694122bbeSMat Martineau 
254794122bbeSMat Martineau 		if (len <= pdu_len) {
254894122bbeSMat Martineau 			sar = L2CAP_SAR_END;
254994122bbeSMat Martineau 			pdu_len = len;
255094122bbeSMat Martineau 		} else {
255194122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
255294122bbeSMat Martineau 		}
255394122bbeSMat Martineau 	}
255494122bbeSMat Martineau 
2555f0f62799SGustavo Padovan 	return 0;
25560a708f8fSGustavo F. Padovan }
25570a708f8fSGustavo F. Padovan 
2558177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2559177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2560177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2561177f8f2bSJohan Hedberg {
2562177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2563177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2564177f8f2bSJohan Hedberg 	int err, count, hlen;
2565177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2566177f8f2bSJohan Hedberg 
2567177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2568177f8f2bSJohan Hedberg 
2569177f8f2bSJohan Hedberg 	if (!conn)
2570177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2571177f8f2bSJohan Hedberg 
2572177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2573177f8f2bSJohan Hedberg 
2574177f8f2bSJohan Hedberg 	if (sdulen)
2575177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2576177f8f2bSJohan Hedberg 
2577177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2578177f8f2bSJohan Hedberg 
2579177f8f2bSJohan Hedberg 	skb = chan->ops->alloc_skb(chan, count + hlen,
2580177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2581177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2582177f8f2bSJohan Hedberg 		return skb;
2583177f8f2bSJohan Hedberg 
2584177f8f2bSJohan Hedberg 	/* Create L2CAP header */
2585177f8f2bSJohan Hedberg 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
2586177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2587177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2588177f8f2bSJohan Hedberg 
2589177f8f2bSJohan Hedberg 	if (sdulen)
2590177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2591177f8f2bSJohan Hedberg 
2592177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2593177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2594177f8f2bSJohan Hedberg 		kfree_skb(skb);
2595177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2596177f8f2bSJohan Hedberg 	}
2597177f8f2bSJohan Hedberg 
2598177f8f2bSJohan Hedberg 	return skb;
2599177f8f2bSJohan Hedberg }
2600177f8f2bSJohan Hedberg 
2601177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2602177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2603177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2604177f8f2bSJohan Hedberg {
2605177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2606177f8f2bSJohan Hedberg 	size_t pdu_len;
2607177f8f2bSJohan Hedberg 	u16 sdu_len;
2608177f8f2bSJohan Hedberg 
2609177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2610177f8f2bSJohan Hedberg 
2611177f8f2bSJohan Hedberg 	pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE;
2612177f8f2bSJohan Hedberg 
2613177f8f2bSJohan Hedberg 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
2614177f8f2bSJohan Hedberg 
2615177f8f2bSJohan Hedberg 	sdu_len = len;
2616177f8f2bSJohan Hedberg 	pdu_len -= L2CAP_SDULEN_SIZE;
2617177f8f2bSJohan Hedberg 
2618177f8f2bSJohan Hedberg 	while (len > 0) {
2619177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2620177f8f2bSJohan Hedberg 			pdu_len = len;
2621177f8f2bSJohan Hedberg 
2622177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2623177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2624177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2625177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2626177f8f2bSJohan Hedberg 		}
2627177f8f2bSJohan Hedberg 
2628177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2629177f8f2bSJohan Hedberg 
2630177f8f2bSJohan Hedberg 		len -= pdu_len;
2631177f8f2bSJohan Hedberg 
2632177f8f2bSJohan Hedberg 		if (sdu_len) {
2633177f8f2bSJohan Hedberg 			sdu_len = 0;
2634177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2635177f8f2bSJohan Hedberg 		}
2636177f8f2bSJohan Hedberg 	}
2637177f8f2bSJohan Hedberg 
2638177f8f2bSJohan Hedberg 	return 0;
2639177f8f2bSJohan Hedberg }
2640177f8f2bSJohan Hedberg 
26415e59b791SLuiz Augusto von Dentz int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
26425e59b791SLuiz Augusto von Dentz 		    u32 priority)
26439a91a04aSGustavo F. Padovan {
26449a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26459a91a04aSGustavo F. Padovan 	int err;
264694122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26479a91a04aSGustavo F. Padovan 
264831e8ce80SSeung-Woo Kim 	if (!chan->conn)
264931e8ce80SSeung-Woo Kim 		return -ENOTCONN;
265031e8ce80SSeung-Woo Kim 
26519a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2652715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26535e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_connless_pdu(chan, msg, len, priority);
26549a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26559a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26569a91a04aSGustavo F. Padovan 
26579a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26589a91a04aSGustavo F. Padovan 		return len;
26599a91a04aSGustavo F. Padovan 	}
26609a91a04aSGustavo F. Padovan 
26619a91a04aSGustavo F. Padovan 	switch (chan->mode) {
266238319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
2663177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2664177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2665177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2666177f8f2bSJohan Hedberg 
2667fad5fc89SJohan Hedberg 		if (!chan->tx_credits)
2668fad5fc89SJohan Hedberg 			return -EAGAIN;
2669fad5fc89SJohan Hedberg 
2670177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2671177f8f2bSJohan Hedberg 
2672177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2673177f8f2bSJohan Hedberg 
2674177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2675177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2676177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2677177f8f2bSJohan Hedberg 		}
2678177f8f2bSJohan Hedberg 
2679177f8f2bSJohan Hedberg 		if (err)
2680177f8f2bSJohan Hedberg 			return err;
2681177f8f2bSJohan Hedberg 
2682177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2683177f8f2bSJohan Hedberg 
2684177f8f2bSJohan Hedberg 		while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
2685177f8f2bSJohan Hedberg 			l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
2686177f8f2bSJohan Hedberg 			chan->tx_credits--;
2687177f8f2bSJohan Hedberg 		}
2688177f8f2bSJohan Hedberg 
2689177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2690177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2691177f8f2bSJohan Hedberg 
2692177f8f2bSJohan Hedberg 		err = len;
2693177f8f2bSJohan Hedberg 
2694177f8f2bSJohan Hedberg 		break;
2695177f8f2bSJohan Hedberg 
2696fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
26979a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
26989a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
26999a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
27009a91a04aSGustavo F. Padovan 
27019a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
27025e59b791SLuiz Augusto von Dentz 		skb = l2cap_create_basic_pdu(chan, msg, len, priority);
27039a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
27049a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
27059a91a04aSGustavo F. Padovan 
27069a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
27079a91a04aSGustavo F. Padovan 		err = len;
27089a91a04aSGustavo F. Padovan 		break;
27099a91a04aSGustavo F. Padovan 
27109a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27119a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
271294122bbeSMat Martineau 		/* Check outgoing MTU */
271394122bbeSMat Martineau 		if (len > chan->omtu) {
271494122bbeSMat Martineau 			err = -EMSGSIZE;
27159a91a04aSGustavo F. Padovan 			break;
27169a91a04aSGustavo F. Padovan 		}
27179a91a04aSGustavo F. Padovan 
271894122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
271994122bbeSMat Martineau 
272094122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
272194122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
272294122bbeSMat Martineau 		 * allocation.
272394122bbeSMat Martineau 		 */
272494122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
272594122bbeSMat Martineau 
272694122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
272794122bbeSMat Martineau 		 * check that it is still connected.
272894122bbeSMat Martineau 		 */
272994122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
273094122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
273194122bbeSMat Martineau 			err = -ENOTCONN;
27329a91a04aSGustavo F. Padovan 		}
27339a91a04aSGustavo F. Padovan 
273494122bbeSMat Martineau 		if (err)
273594122bbeSMat Martineau 			break;
273694122bbeSMat Martineau 
27373733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2738d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27393733937dSMat Martineau 		else
2740d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
274194122bbeSMat Martineau 
27429a91a04aSGustavo F. Padovan 		err = len;
27439a91a04aSGustavo F. Padovan 
274494122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
274594122bbeSMat Martineau 		 * seg_queue and need to be purged.
274694122bbeSMat Martineau 		 */
274794122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27489a91a04aSGustavo F. Padovan 		break;
27499a91a04aSGustavo F. Padovan 
27509a91a04aSGustavo F. Padovan 	default:
27519a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27529a91a04aSGustavo F. Padovan 		err = -EBADFD;
27539a91a04aSGustavo F. Padovan 	}
27549a91a04aSGustavo F. Padovan 
27559a91a04aSGustavo F. Padovan 	return err;
27569a91a04aSGustavo F. Padovan }
27579a91a04aSGustavo F. Padovan 
2758d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2759d2a7ac5dSMat Martineau {
2760bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2761bed68bdeSMat Martineau 	u16 seq;
2762bed68bdeSMat Martineau 
2763b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2764bed68bdeSMat Martineau 
2765bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2766bed68bdeSMat Martineau 	control.sframe = 1;
2767bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2768bed68bdeSMat Martineau 
2769bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2770bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2771bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2772bed68bdeSMat Martineau 			control.reqseq = seq;
2773bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2774bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2775bed68bdeSMat Martineau 		}
2776bed68bdeSMat Martineau 	}
2777bed68bdeSMat Martineau 
2778bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2779d2a7ac5dSMat Martineau }
2780d2a7ac5dSMat Martineau 
2781d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2782d2a7ac5dSMat Martineau {
2783bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2784bed68bdeSMat Martineau 
2785bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2786bed68bdeSMat Martineau 
2787bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2788bed68bdeSMat Martineau 		return;
2789bed68bdeSMat Martineau 
2790bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2791bed68bdeSMat Martineau 	control.sframe = 1;
2792bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2793bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2794bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2795d2a7ac5dSMat Martineau }
2796d2a7ac5dSMat Martineau 
2797d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2798d2a7ac5dSMat Martineau {
2799bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2800bed68bdeSMat Martineau 	u16 initial_head;
2801bed68bdeSMat Martineau 	u16 seq;
2802bed68bdeSMat Martineau 
2803b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2804bed68bdeSMat Martineau 
2805bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2806bed68bdeSMat Martineau 	control.sframe = 1;
2807bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2808bed68bdeSMat Martineau 
2809bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2810bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2811bed68bdeSMat Martineau 
2812bed68bdeSMat Martineau 	do {
2813bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2814bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2815bed68bdeSMat Martineau 			break;
2816bed68bdeSMat Martineau 
2817bed68bdeSMat Martineau 		control.reqseq = seq;
2818bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2819bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2820bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2821d2a7ac5dSMat Martineau }
2822d2a7ac5dSMat Martineau 
2823608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2824608bcc6dSMat Martineau {
2825608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2826608bcc6dSMat Martineau 	u16 ackseq;
2827608bcc6dSMat Martineau 
2828b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2829608bcc6dSMat Martineau 
2830608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2831608bcc6dSMat Martineau 		return;
2832608bcc6dSMat Martineau 
2833b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2834608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2835608bcc6dSMat Martineau 
2836608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2837608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2838608bcc6dSMat Martineau 
2839608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2840608bcc6dSMat Martineau 		if (acked_skb) {
2841608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2842608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2843608bcc6dSMat Martineau 			chan->unacked_frames--;
2844608bcc6dSMat Martineau 		}
2845608bcc6dSMat Martineau 	}
2846608bcc6dSMat Martineau 
2847608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2848608bcc6dSMat Martineau 
2849608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2850608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2851608bcc6dSMat Martineau 
2852b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2853608bcc6dSMat Martineau }
2854608bcc6dSMat Martineau 
2855608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2856608bcc6dSMat Martineau {
2857608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2858608bcc6dSMat Martineau 
2859608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2860608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2861608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2862608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2863608bcc6dSMat Martineau }
2864608bcc6dSMat Martineau 
2865d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2866608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2867608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2868608bcc6dSMat Martineau {
2869608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2870608bcc6dSMat Martineau 	       event);
2871608bcc6dSMat Martineau 
2872608bcc6dSMat Martineau 	switch (event) {
2873608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2874608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2875608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2876608bcc6dSMat Martineau 
2877608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2878608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2879608bcc6dSMat Martineau 		break;
2880608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2881608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2882608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2883608bcc6dSMat Martineau 
2884608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2885608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2886608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2887608bcc6dSMat Martineau 			 */
2888608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2889608bcc6dSMat Martineau 		}
2890608bcc6dSMat Martineau 
2891608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2892608bcc6dSMat Martineau 
2893608bcc6dSMat Martineau 		break;
2894608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2895608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2896608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2897608bcc6dSMat Martineau 
2898608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2899608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2900608bcc6dSMat Martineau 
2901608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2902608bcc6dSMat Martineau 			local_control.sframe = 1;
2903608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2904608bcc6dSMat Martineau 			local_control.poll = 1;
2905608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2906a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2907608bcc6dSMat Martineau 
2908608bcc6dSMat Martineau 			chan->retry_count = 1;
2909608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2910608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2911608bcc6dSMat Martineau 		}
2912608bcc6dSMat Martineau 		break;
2913608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2914608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2915608bcc6dSMat Martineau 		break;
2916608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2917608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2918608bcc6dSMat Martineau 		chan->retry_count = 1;
2919608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2920608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2921608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2922608bcc6dSMat Martineau 		break;
2923608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2924608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2925608bcc6dSMat Martineau 		chan->retry_count = 1;
2926608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2927608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2928608bcc6dSMat Martineau 		break;
2929608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2930608bcc6dSMat Martineau 		/* Nothing to process */
2931608bcc6dSMat Martineau 		break;
2932608bcc6dSMat Martineau 	default:
2933608bcc6dSMat Martineau 		break;
2934608bcc6dSMat Martineau 	}
2935608bcc6dSMat Martineau }
2936608bcc6dSMat Martineau 
2937d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2938608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2939608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2940608bcc6dSMat Martineau {
2941608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2942608bcc6dSMat Martineau 	       event);
2943608bcc6dSMat Martineau 
2944608bcc6dSMat Martineau 	switch (event) {
2945608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2946608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2947608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2948608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2949608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2950608bcc6dSMat Martineau 		break;
2951608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2952608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2953608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2954608bcc6dSMat Martineau 
2955608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2956608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2957608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2958608bcc6dSMat Martineau 			 */
2959608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2960608bcc6dSMat Martineau 		}
2961608bcc6dSMat Martineau 
2962608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2963608bcc6dSMat Martineau 
2964608bcc6dSMat Martineau 		break;
2965608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2966608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2967608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2968608bcc6dSMat Martineau 
2969608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2970608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2971608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2972608bcc6dSMat Martineau 			local_control.sframe = 1;
2973608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2974608bcc6dSMat Martineau 			local_control.poll = 1;
2975608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2976a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2977608bcc6dSMat Martineau 
2978608bcc6dSMat Martineau 			chan->retry_count = 1;
2979608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2980608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2981608bcc6dSMat Martineau 		}
2982608bcc6dSMat Martineau 		break;
2983608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2984608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2985608bcc6dSMat Martineau 
2986608bcc6dSMat Martineau 		/* Fall through */
2987608bcc6dSMat Martineau 
2988608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2989608bcc6dSMat Martineau 		if (control && control->final) {
2990608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
2991608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
2992608bcc6dSMat Martineau 				__set_retrans_timer(chan);
2993608bcc6dSMat Martineau 			chan->retry_count = 0;
2994608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
2995608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
2996608bcc6dSMat Martineau 		}
2997608bcc6dSMat Martineau 		break;
2998608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2999608bcc6dSMat Martineau 		/* Ignore */
3000608bcc6dSMat Martineau 		break;
3001608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
3002608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
3003608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
3004608bcc6dSMat Martineau 			__set_monitor_timer(chan);
3005608bcc6dSMat Martineau 			chan->retry_count++;
3006608bcc6dSMat Martineau 		} else {
30075e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
3008608bcc6dSMat Martineau 		}
3009608bcc6dSMat Martineau 		break;
3010608bcc6dSMat Martineau 	default:
3011608bcc6dSMat Martineau 		break;
3012608bcc6dSMat Martineau 	}
3013608bcc6dSMat Martineau }
3014608bcc6dSMat Martineau 
3015d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
3016608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
3017608bcc6dSMat Martineau {
3018608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
3019608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
3020608bcc6dSMat Martineau 
3021608bcc6dSMat Martineau 	switch (chan->tx_state) {
3022608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3023d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3024608bcc6dSMat Martineau 		break;
3025608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3026d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3027608bcc6dSMat Martineau 		break;
3028608bcc6dSMat Martineau 	default:
3029608bcc6dSMat Martineau 		/* Ignore event */
3030608bcc6dSMat Martineau 		break;
3031608bcc6dSMat Martineau 	}
3032608bcc6dSMat Martineau }
3033608bcc6dSMat Martineau 
30344b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30354b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30364b51dae9SMat Martineau {
30374b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3038401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30394b51dae9SMat Martineau }
30404b51dae9SMat Martineau 
3041f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3042f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3043f80842a8SMat Martineau {
3044f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3045401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3046f80842a8SMat Martineau }
3047f80842a8SMat Martineau 
30480a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30490a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30500a708f8fSGustavo F. Padovan {
30510a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
305248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30530a708f8fSGustavo F. Padovan 
30540a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30550a708f8fSGustavo F. Padovan 
30563df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30573d57dc68SGustavo F. Padovan 
30583df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3059715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30600a708f8fSGustavo F. Padovan 			continue;
30610a708f8fSGustavo F. Padovan 
30627f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
30637f5396a7SGustavo Padovan 		if (bt_cb(skb)->chan == chan)
30640a708f8fSGustavo F. Padovan 			continue;
30657f5396a7SGustavo Padovan 
30668bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30670a708f8fSGustavo F. Padovan 		if (!nskb)
30680a708f8fSGustavo F. Padovan 			continue;
306980b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30700a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30710a708f8fSGustavo F. Padovan 	}
30723d57dc68SGustavo F. Padovan 
30733df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30740a708f8fSGustavo F. Padovan }
30750a708f8fSGustavo F. Padovan 
30760a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3077b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3078b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30790a708f8fSGustavo F. Padovan {
30800a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30810a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30820a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30830a708f8fSGustavo F. Padovan 	int len, count;
30840a708f8fSGustavo F. Padovan 
3085b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30860a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
30870a708f8fSGustavo F. Padovan 
3088300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3089300b962eSAnderson Lizardo 		return NULL;
3090300b962eSAnderson Lizardo 
30910a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
30920a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
30930a708f8fSGustavo F. Padovan 
30948bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
30950a708f8fSGustavo F. Padovan 	if (!skb)
30960a708f8fSGustavo F. Padovan 		return NULL;
30970a708f8fSGustavo F. Padovan 
30980a708f8fSGustavo F. Padovan 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
30990a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
31003300d9a9SClaudio Takahasi 
31013300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3102ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING);
31033300d9a9SClaudio Takahasi 	else
3104ac73498cSAndrei Emeltchenko 		lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING);
31050a708f8fSGustavo F. Padovan 
31060a708f8fSGustavo F. Padovan 	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
31070a708f8fSGustavo F. Padovan 	cmd->code  = code;
31080a708f8fSGustavo F. Padovan 	cmd->ident = ident;
31090a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
31100a708f8fSGustavo F. Padovan 
31110a708f8fSGustavo F. Padovan 	if (dlen) {
31120a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
31130a708f8fSGustavo F. Padovan 		memcpy(skb_put(skb, count), data, count);
31140a708f8fSGustavo F. Padovan 		data += count;
31150a708f8fSGustavo F. Padovan 	}
31160a708f8fSGustavo F. Padovan 
31170a708f8fSGustavo F. Padovan 	len -= skb->len;
31180a708f8fSGustavo F. Padovan 
31190a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
31200a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31210a708f8fSGustavo F. Padovan 	while (len) {
31220a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31230a708f8fSGustavo F. Padovan 
31248bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31250a708f8fSGustavo F. Padovan 		if (!*frag)
31260a708f8fSGustavo F. Padovan 			goto fail;
31270a708f8fSGustavo F. Padovan 
31280a708f8fSGustavo F. Padovan 		memcpy(skb_put(*frag, count), data, count);
31290a708f8fSGustavo F. Padovan 
31300a708f8fSGustavo F. Padovan 		len  -= count;
31310a708f8fSGustavo F. Padovan 		data += count;
31320a708f8fSGustavo F. Padovan 
31330a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31340a708f8fSGustavo F. Padovan 	}
31350a708f8fSGustavo F. Padovan 
31360a708f8fSGustavo F. Padovan 	return skb;
31370a708f8fSGustavo F. Padovan 
31380a708f8fSGustavo F. Padovan fail:
31390a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31400a708f8fSGustavo F. Padovan 	return NULL;
31410a708f8fSGustavo F. Padovan }
31420a708f8fSGustavo F. Padovan 
31432d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31442d792818SGustavo Padovan 				     unsigned long *val)
31450a708f8fSGustavo F. Padovan {
31460a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31470a708f8fSGustavo F. Padovan 	int len;
31480a708f8fSGustavo F. Padovan 
31490a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31500a708f8fSGustavo F. Padovan 	*ptr += len;
31510a708f8fSGustavo F. Padovan 
31520a708f8fSGustavo F. Padovan 	*type = opt->type;
31530a708f8fSGustavo F. Padovan 	*olen = opt->len;
31540a708f8fSGustavo F. Padovan 
31550a708f8fSGustavo F. Padovan 	switch (opt->len) {
31560a708f8fSGustavo F. Padovan 	case 1:
31570a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31580a708f8fSGustavo F. Padovan 		break;
31590a708f8fSGustavo F. Padovan 
31600a708f8fSGustavo F. Padovan 	case 2:
31610a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31620a708f8fSGustavo F. Padovan 		break;
31630a708f8fSGustavo F. Padovan 
31640a708f8fSGustavo F. Padovan 	case 4:
31650a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31660a708f8fSGustavo F. Padovan 		break;
31670a708f8fSGustavo F. Padovan 
31680a708f8fSGustavo F. Padovan 	default:
31690a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31700a708f8fSGustavo F. Padovan 		break;
31710a708f8fSGustavo F. Padovan 	}
31720a708f8fSGustavo F. Padovan 
3173b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31740a708f8fSGustavo F. Padovan 	return len;
31750a708f8fSGustavo F. Padovan }
31760a708f8fSGustavo F. Padovan 
31770a708f8fSGustavo F. Padovan static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
31780a708f8fSGustavo F. Padovan {
31790a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31800a708f8fSGustavo F. Padovan 
3181b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31820a708f8fSGustavo F. Padovan 
31830a708f8fSGustavo F. Padovan 	opt->type = type;
31840a708f8fSGustavo F. Padovan 	opt->len  = len;
31850a708f8fSGustavo F. Padovan 
31860a708f8fSGustavo F. Padovan 	switch (len) {
31870a708f8fSGustavo F. Padovan 	case 1:
31880a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
31890a708f8fSGustavo F. Padovan 		break;
31900a708f8fSGustavo F. Padovan 
31910a708f8fSGustavo F. Padovan 	case 2:
31920a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
31930a708f8fSGustavo F. Padovan 		break;
31940a708f8fSGustavo F. Padovan 
31950a708f8fSGustavo F. Padovan 	case 4:
31960a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
31970a708f8fSGustavo F. Padovan 		break;
31980a708f8fSGustavo F. Padovan 
31990a708f8fSGustavo F. Padovan 	default:
32000a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
32010a708f8fSGustavo F. Padovan 		break;
32020a708f8fSGustavo F. Padovan 	}
32030a708f8fSGustavo F. Padovan 
32040a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
32050a708f8fSGustavo F. Padovan }
32060a708f8fSGustavo F. Padovan 
3207f89cef09SAndrei Emeltchenko static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
3208f89cef09SAndrei Emeltchenko {
3209f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3210f89cef09SAndrei Emeltchenko 
3211f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3212f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3213f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3214f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3215f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3216f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3217ac73498cSAndrei Emeltchenko 		efs.acc_lat	= __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
32188936fa6dSAndrei Emeltchenko 		efs.flush_to	= __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3219f89cef09SAndrei Emeltchenko 		break;
3220f89cef09SAndrei Emeltchenko 
3221f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3222f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3223f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3224f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3225f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3226f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3227f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3228f89cef09SAndrei Emeltchenko 		break;
3229f89cef09SAndrei Emeltchenko 
3230f89cef09SAndrei Emeltchenko 	default:
3231f89cef09SAndrei Emeltchenko 		return;
3232f89cef09SAndrei Emeltchenko 	}
3233f89cef09SAndrei Emeltchenko 
3234f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3235f89cef09SAndrei Emeltchenko 			   (unsigned long) &efs);
3236f89cef09SAndrei Emeltchenko }
3237f89cef09SAndrei Emeltchenko 
3238721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32390a708f8fSGustavo F. Padovan {
3240721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3241721c4181SGustavo F. Padovan 					       ack_timer.work);
32420362520bSMat Martineau 	u16 frames_to_ack;
32430a708f8fSGustavo F. Padovan 
32442fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32452fb9b3d4SGustavo F. Padovan 
32466be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32476be36555SAndrei Emeltchenko 
32480362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32490362520bSMat Martineau 				     chan->last_acked_seq);
32500362520bSMat Martineau 
32510362520bSMat Martineau 	if (frames_to_ack)
32520362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32536be36555SAndrei Emeltchenko 
32546be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
325509bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32560a708f8fSGustavo F. Padovan }
32570a708f8fSGustavo F. Padovan 
3258466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32590a708f8fSGustavo F. Padovan {
32603c588192SMat Martineau 	int err;
32613c588192SMat Martineau 
3262105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3263105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
326442e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32656a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
326642e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32676a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3268105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3269105bdf9eSMat Martineau 	chan->sdu = NULL;
3270105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3271105bdf9eSMat Martineau 	chan->sdu_len = 0;
3272105bdf9eSMat Martineau 
3273d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3274d34c34fbSMat Martineau 
32756ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32766ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
327708333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
327808333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
327908333283SMat Martineau 
3280105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3281105bdf9eSMat Martineau 		return 0;
3282105bdf9eSMat Martineau 
3283105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3284105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
32850a708f8fSGustavo F. Padovan 
3286721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3287721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3288721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
32890a708f8fSGustavo F. Padovan 
3290f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
32910a708f8fSGustavo F. Padovan 
32923c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
32933c588192SMat Martineau 	if (err < 0)
32943c588192SMat Martineau 		return err;
32953c588192SMat Martineau 
32969dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
32979dc9affcSMat Martineau 	if (err < 0)
32989dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
32999dc9affcSMat Martineau 
33009dc9affcSMat Martineau 	return err;
33010a708f8fSGustavo F. Padovan }
33020a708f8fSGustavo F. Padovan 
33030a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
33040a708f8fSGustavo F. Padovan {
33050a708f8fSGustavo F. Padovan 	switch (mode) {
33060a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33070a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33080a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
33090a708f8fSGustavo F. Padovan 			return mode;
33100a708f8fSGustavo F. Padovan 		/* fall through */
33110a708f8fSGustavo F. Padovan 	default:
33120a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
33130a708f8fSGustavo F. Padovan 	}
33140a708f8fSGustavo F. Padovan }
33150a708f8fSGustavo F. Padovan 
3316848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
33176327eb98SAndrei Emeltchenko {
3318848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
33196327eb98SAndrei Emeltchenko }
33206327eb98SAndrei Emeltchenko 
3321848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3322f89cef09SAndrei Emeltchenko {
3323848566b3SMarcel Holtmann 	return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
3324f89cef09SAndrei Emeltchenko }
3325f89cef09SAndrei Emeltchenko 
332636c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
332736c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
332836c86c85SMat Martineau {
33296ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
333036c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
333136c86c85SMat Martineau 
333236c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
333336c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
333436c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
333536c86c85SMat Martineau 		 * controllers is 10 seconds.
333636c86c85SMat Martineau 		 *
333736c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
333836c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
333936c86c85SMat Martineau 		 * will result in a timeout that meets the above
334036c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
334136c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
334236c86c85SMat Martineau 		 */
334336c86c85SMat Martineau 
334436c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
334536c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
334636c86c85SMat Martineau 
334736c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
334836c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
334936c86c85SMat Martineau 		 * controller.
335036c86c85SMat Martineau 		 */
335136c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
335236c86c85SMat Martineau 
335336c86c85SMat Martineau 		if (ertm_to > 0xffff)
335436c86c85SMat Martineau 			ertm_to = 0xffff;
335536c86c85SMat Martineau 
335636c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
335736c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
335836c86c85SMat Martineau 	} else {
335936c86c85SMat Martineau 		rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
336036c86c85SMat Martineau 		rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
336136c86c85SMat Martineau 	}
336236c86c85SMat Martineau }
336336c86c85SMat Martineau 
33646327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33656327eb98SAndrei Emeltchenko {
33666327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3367848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33686327eb98SAndrei Emeltchenko 		/* use extended control field */
33696327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3370836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3371836be934SAndrei Emeltchenko 	} else {
33726327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33736327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3374836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3375836be934SAndrei Emeltchenko 	}
3376c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33776327eb98SAndrei Emeltchenko }
33786327eb98SAndrei Emeltchenko 
3379710f9b0aSGustavo F. Padovan static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
33800a708f8fSGustavo F. Padovan {
33810a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
33820c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
33830a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3384c8f79162SAndrei Emeltchenko 	u16 size;
33850a708f8fSGustavo F. Padovan 
338649208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
33870a708f8fSGustavo F. Padovan 
338873ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
33890a708f8fSGustavo F. Padovan 		goto done;
33900a708f8fSGustavo F. Padovan 
33910c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
33920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3394c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
33950a708f8fSGustavo F. Padovan 			break;
33960a708f8fSGustavo F. Padovan 
3397848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3398f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3399f89cef09SAndrei Emeltchenko 
34000a708f8fSGustavo F. Padovan 		/* fall through */
34010a708f8fSGustavo F. Padovan 	default:
34028c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
34030a708f8fSGustavo F. Padovan 		break;
34040a708f8fSGustavo F. Padovan 	}
34050a708f8fSGustavo F. Padovan 
34060a708f8fSGustavo F. Padovan done:
34070c1bc5c6SGustavo F. Padovan 	if (chan->imtu != L2CAP_DEFAULT_MTU)
34080c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
34090a708f8fSGustavo F. Padovan 
34100c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34110a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
34128c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
34138c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
34140a708f8fSGustavo F. Padovan 			break;
34150a708f8fSGustavo F. Padovan 
34160a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
34170a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34180a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34190a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34200a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34210a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34220a708f8fSGustavo F. Padovan 
34230a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34240a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34250a708f8fSGustavo F. Padovan 		break;
34260a708f8fSGustavo F. Padovan 
34270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34280a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
342947d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
343036c86c85SMat Martineau 
343136c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3432c8f79162SAndrei Emeltchenko 
3433c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34342d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3435c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3436c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34370a708f8fSGustavo F. Padovan 
34386327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
34396327eb98SAndrei Emeltchenko 
34406327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
34416327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
34420a708f8fSGustavo F. Padovan 
34430a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34440a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34450a708f8fSGustavo F. Padovan 
3446f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3447f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3448f89cef09SAndrei Emeltchenko 
34496327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
34506327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
34516327eb98SAndrei Emeltchenko 					   chan->tx_win);
345260918918SAndrei Emeltchenko 
345360918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
345460918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3455f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
345660918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
345760918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
345860918918SAndrei Emeltchenko 						   chan->fcs);
345960918918SAndrei Emeltchenko 			}
34600a708f8fSGustavo F. Padovan 		break;
34610a708f8fSGustavo F. Padovan 
34620a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3463273759e2SMat Martineau 		l2cap_txwin_setup(chan);
34640a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
34650a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34660a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34670a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34680a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3469c8f79162SAndrei Emeltchenko 
3470c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34712d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3472c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3473c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
34740a708f8fSGustavo F. Padovan 
34750a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
34760a708f8fSGustavo F. Padovan 				   (unsigned long) &rfc);
34770a708f8fSGustavo F. Padovan 
3478f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3479f89cef09SAndrei Emeltchenko 			l2cap_add_opt_efs(&ptr, chan);
3480f89cef09SAndrei Emeltchenko 
348160918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
348247d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3483f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
348447d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
348560918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
348660918918SAndrei Emeltchenko 						   chan->fcs);
34870a708f8fSGustavo F. Padovan 			}
34880a708f8fSGustavo F. Padovan 		break;
34890a708f8fSGustavo F. Padovan 	}
34900a708f8fSGustavo F. Padovan 
3491fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
349259e54bd1SAndrei Emeltchenko 	req->flags = __constant_cpu_to_le16(0);
34930a708f8fSGustavo F. Padovan 
34940a708f8fSGustavo F. Padovan 	return ptr - data;
34950a708f8fSGustavo F. Padovan }
34960a708f8fSGustavo F. Padovan 
349773ffa904SGustavo F. Padovan static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34980a708f8fSGustavo F. Padovan {
34990a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
35000a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
350173ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
350273ffa904SGustavo F. Padovan 	int len = chan->conf_len;
35030a708f8fSGustavo F. Padovan 	int type, hint, olen;
35040a708f8fSGustavo F. Padovan 	unsigned long val;
35050a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
350642dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
350742dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
35080a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
35090a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3510c8f79162SAndrei Emeltchenko 	u16 size;
35110a708f8fSGustavo F. Padovan 
351273ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
35130a708f8fSGustavo F. Padovan 
35140a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35150a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
35160a708f8fSGustavo F. Padovan 
35170a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
35180a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
35190a708f8fSGustavo F. Padovan 
35200a708f8fSGustavo F. Padovan 		switch (type) {
35210a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
35220a708f8fSGustavo F. Padovan 			mtu = val;
35230a708f8fSGustavo F. Padovan 			break;
35240a708f8fSGustavo F. Padovan 
35250a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
35260c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35270a708f8fSGustavo F. Padovan 			break;
35280a708f8fSGustavo F. Padovan 
35290a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
35300a708f8fSGustavo F. Padovan 			break;
35310a708f8fSGustavo F. Padovan 
35320a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
35330a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
35340a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *) val, olen);
35350a708f8fSGustavo F. Padovan 			break;
35360a708f8fSGustavo F. Padovan 
35370a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
35380a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3539f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
354042dceae2SAndrei Emeltchenko 			break;
35410a708f8fSGustavo F. Padovan 
354242dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
354342dceae2SAndrei Emeltchenko 			remote_efs = 1;
354442dceae2SAndrei Emeltchenko 			if (olen == sizeof(efs))
354542dceae2SAndrei Emeltchenko 				memcpy(&efs, (void *) val, olen);
35460a708f8fSGustavo F. Padovan 			break;
35470a708f8fSGustavo F. Padovan 
35486327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3549848566b3SMarcel Holtmann 			if (!chan->conn->hs_enabled)
35506327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
35516327eb98SAndrei Emeltchenko 
35526327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
35536327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3554836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
35556327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
35560a708f8fSGustavo F. Padovan 			break;
35570a708f8fSGustavo F. Padovan 
35580a708f8fSGustavo F. Padovan 		default:
35590a708f8fSGustavo F. Padovan 			if (hint)
35600a708f8fSGustavo F. Padovan 				break;
35610a708f8fSGustavo F. Padovan 
35620a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
35630a708f8fSGustavo F. Padovan 			*((u8 *) ptr++) = type;
35640a708f8fSGustavo F. Padovan 			break;
35650a708f8fSGustavo F. Padovan 		}
35660a708f8fSGustavo F. Padovan 	}
35670a708f8fSGustavo F. Padovan 
356873ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
35690a708f8fSGustavo F. Padovan 		goto done;
35700a708f8fSGustavo F. Padovan 
35710c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
35720a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
35730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3574c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
35750c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
35768c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
35770a708f8fSGustavo F. Padovan 			break;
35780a708f8fSGustavo F. Padovan 		}
35790a708f8fSGustavo F. Padovan 
358042dceae2SAndrei Emeltchenko 		if (remote_efs) {
3581848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
358242dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
358342dceae2SAndrei Emeltchenko 			else
358442dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
358542dceae2SAndrei Emeltchenko 		}
358642dceae2SAndrei Emeltchenko 
35870c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
35880a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
35890a708f8fSGustavo F. Padovan 
35900a708f8fSGustavo F. Padovan 		break;
35910a708f8fSGustavo F. Padovan 	}
35920a708f8fSGustavo F. Padovan 
35930a708f8fSGustavo F. Padovan done:
35940c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
35950a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
35960c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
35970a708f8fSGustavo F. Padovan 
359873ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
35990a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36000a708f8fSGustavo F. Padovan 
36012d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
36022d792818SGustavo Padovan 				   (unsigned long) &rfc);
36030a708f8fSGustavo F. Padovan 	}
36040a708f8fSGustavo F. Padovan 
36050a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
36060a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
36070a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
36080a708f8fSGustavo F. Padovan 
36090a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
36100a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36110a708f8fSGustavo F. Padovan 		else {
36120c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3613c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
36140a708f8fSGustavo F. Padovan 		}
36150c1bc5c6SGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
36160a708f8fSGustavo F. Padovan 
361742dceae2SAndrei Emeltchenko 		if (remote_efs) {
361842dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
361942dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
362042dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
362142dceae2SAndrei Emeltchenko 
362242dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
362342dceae2SAndrei Emeltchenko 
362442dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
362542dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
362642dceae2SAndrei Emeltchenko 
362742dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
362842dceae2SAndrei Emeltchenko 						   sizeof(efs),
362942dceae2SAndrei Emeltchenko 						   (unsigned long) &efs);
36300e8b207eSAndrei Emeltchenko 			} else {
36313e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
36320e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
36330e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
363442dceae2SAndrei Emeltchenko 			}
363542dceae2SAndrei Emeltchenko 		}
363642dceae2SAndrei Emeltchenko 
36370a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
36380a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
363947d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3640c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36410a708f8fSGustavo F. Padovan 			break;
36420a708f8fSGustavo F. Padovan 
36430a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
36446327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
36452c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
36466327eb98SAndrei Emeltchenko 			else
36476327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
36486327eb98SAndrei Emeltchenko 
36492c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
36500a708f8fSGustavo F. Padovan 
3651c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36522d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36532d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3654c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3655c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36560a708f8fSGustavo F. Padovan 
365736c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
36580a708f8fSGustavo F. Padovan 
3659c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36600a708f8fSGustavo F. Padovan 
36610a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
36620a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
36630a708f8fSGustavo F. Padovan 
366442dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
366542dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
366642dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
366742dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
366842dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
366942dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
367042dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
367142dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
367242dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
367342dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
367442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
36752d792818SGustavo Padovan 						   sizeof(efs),
36762d792818SGustavo Padovan 						   (unsigned long) &efs);
367742dceae2SAndrei Emeltchenko 			}
36780a708f8fSGustavo F. Padovan 			break;
36790a708f8fSGustavo F. Padovan 
36800a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3681c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
36822d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
36832d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3684c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3685c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
36860a708f8fSGustavo F. Padovan 
3687c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
36880a708f8fSGustavo F. Padovan 
36892d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
36902d792818SGustavo Padovan 					   (unsigned long) &rfc);
36910a708f8fSGustavo F. Padovan 
36920a708f8fSGustavo F. Padovan 			break;
36930a708f8fSGustavo F. Padovan 
36940a708f8fSGustavo F. Padovan 		default:
36950a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36960a708f8fSGustavo F. Padovan 
36970a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
36980c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
36990a708f8fSGustavo F. Padovan 		}
37000a708f8fSGustavo F. Padovan 
37010a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3702c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37030a708f8fSGustavo F. Padovan 	}
3704fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37050a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
370659e54bd1SAndrei Emeltchenko 	rsp->flags  = __constant_cpu_to_le16(0);
37070a708f8fSGustavo F. Padovan 
37080a708f8fSGustavo F. Padovan 	return ptr - data;
37090a708f8fSGustavo F. Padovan }
37100a708f8fSGustavo F. Padovan 
37112d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
37122d792818SGustavo Padovan 				void *data, u16 *result)
37130a708f8fSGustavo F. Padovan {
37140a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
37150a708f8fSGustavo F. Padovan 	void *ptr = req->data;
37160a708f8fSGustavo F. Padovan 	int type, olen;
37170a708f8fSGustavo F. Padovan 	unsigned long val;
371836e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
371966af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
37200a708f8fSGustavo F. Padovan 
3721fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
37220a708f8fSGustavo F. Padovan 
37230a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
37240a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
37250a708f8fSGustavo F. Padovan 
37260a708f8fSGustavo F. Padovan 		switch (type) {
37270a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
37280a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
37290a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
37300c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
37310a708f8fSGustavo F. Padovan 			} else
37320c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
37330c1bc5c6SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
37340a708f8fSGustavo F. Padovan 			break;
37350a708f8fSGustavo F. Padovan 
37360a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
37370c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
37380a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
37390c1bc5c6SGustavo F. Padovan 					   2, chan->flush_to);
37400a708f8fSGustavo F. Padovan 			break;
37410a708f8fSGustavo F. Padovan 
37420a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
37430a708f8fSGustavo F. Padovan 			if (olen == sizeof(rfc))
37440a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
37450a708f8fSGustavo F. Padovan 
3746c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
37470c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
37480a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
37490a708f8fSGustavo F. Padovan 
375047d1ec61SGustavo F. Padovan 			chan->fcs = 0;
37510a708f8fSGustavo F. Padovan 
37520a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
37530a708f8fSGustavo F. Padovan 					   sizeof(rfc), (unsigned long) &rfc);
37540a708f8fSGustavo F. Padovan 			break;
37556327eb98SAndrei Emeltchenko 
37566327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3757c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
37583e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
37593e6b3b95SGustavo F. Padovan 					   chan->tx_win);
37606327eb98SAndrei Emeltchenko 			break;
376166af7aafSAndrei Emeltchenko 
376266af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
376366af7aafSAndrei Emeltchenko 			if (olen == sizeof(efs))
376466af7aafSAndrei Emeltchenko 				memcpy(&efs, (void *)val, olen);
376566af7aafSAndrei Emeltchenko 
376666af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
376766af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
376866af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
376966af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
377066af7aafSAndrei Emeltchenko 
37712d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
37722d792818SGustavo Padovan 					   (unsigned long) &efs);
377366af7aafSAndrei Emeltchenko 			break;
3774cbabee78SAndrei Emeltchenko 
3775cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3776cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3777cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3778f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3779cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3780cbabee78SAndrei Emeltchenko 			break;
37810a708f8fSGustavo F. Padovan 		}
37820a708f8fSGustavo F. Padovan 	}
37830a708f8fSGustavo F. Padovan 
37840c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
37850a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
37860a708f8fSGustavo F. Padovan 
37870c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
37880a708f8fSGustavo F. Padovan 
37890e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
37900a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37910a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
379247d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
379347d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
379447d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3795c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3796c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3797c20f8e35SMat Martineau 						      rfc.txwin_size);
379866af7aafSAndrei Emeltchenko 
379966af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
380066af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
380166af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
380266af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
380366af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
380466af7aafSAndrei Emeltchenko 				chan->local_flush_to =
380566af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
380666af7aafSAndrei Emeltchenko 			}
38070a708f8fSGustavo F. Padovan 			break;
380866af7aafSAndrei Emeltchenko 
38090a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
381047d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38110a708f8fSGustavo F. Padovan 		}
38120a708f8fSGustavo F. Padovan 	}
38130a708f8fSGustavo F. Padovan 
3814fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
381559e54bd1SAndrei Emeltchenko 	req->flags  = __constant_cpu_to_le16(0);
38160a708f8fSGustavo F. Padovan 
38170a708f8fSGustavo F. Padovan 	return ptr - data;
38180a708f8fSGustavo F. Padovan }
38190a708f8fSGustavo F. Padovan 
38202d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
38212d792818SGustavo Padovan 				u16 result, u16 flags)
38220a708f8fSGustavo F. Padovan {
38230a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
38240a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
38250a708f8fSGustavo F. Padovan 
3826fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
38270a708f8fSGustavo F. Padovan 
3828fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
38290a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
38300a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
38310a708f8fSGustavo F. Padovan 
38320a708f8fSGustavo F. Padovan 	return ptr - data;
38330a708f8fSGustavo F. Padovan }
38340a708f8fSGustavo F. Padovan 
383527e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
383627e2d4c8SJohan Hedberg {
383727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
383827e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
383927e2d4c8SJohan Hedberg 
384027e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
384127e2d4c8SJohan Hedberg 
384227e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
384327e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
38443916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
38450cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
384627e2d4c8SJohan Hedberg 	rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
384727e2d4c8SJohan Hedberg 
384827e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
384927e2d4c8SJohan Hedberg 		       &rsp);
385027e2d4c8SJohan Hedberg }
385127e2d4c8SJohan Hedberg 
38528c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3853710f9b0aSGustavo F. Padovan {
3854710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
38558c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3856710f9b0aSGustavo F. Padovan 	u8 buf[128];
3857439f34acSAndrei Emeltchenko 	u8 rsp_code;
3858710f9b0aSGustavo F. Padovan 
3859fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3860fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3861ac73498cSAndrei Emeltchenko 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
3862ac73498cSAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
3863439f34acSAndrei Emeltchenko 
3864439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3865439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3866439f34acSAndrei Emeltchenko 	else
3867439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3868439f34acSAndrei Emeltchenko 
3869439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3870439f34acSAndrei Emeltchenko 
3871439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3872710f9b0aSGustavo F. Padovan 
3873c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3874710f9b0aSGustavo F. Padovan 		return;
3875710f9b0aSGustavo F. Padovan 
3876710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3877710f9b0aSGustavo F. Padovan 		       l2cap_build_conf_req(chan, buf), buf);
3878710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
3879710f9b0aSGustavo F. Padovan }
3880710f9b0aSGustavo F. Padovan 
388147d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
38820a708f8fSGustavo F. Padovan {
38830a708f8fSGustavo F. Padovan 	int type, olen;
38840a708f8fSGustavo F. Padovan 	unsigned long val;
3885c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
3886c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
3887c20f8e35SMat Martineau 	 */
3888c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
3889c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
3890c20f8e35SMat Martineau 		.mode = chan->mode,
3891c20f8e35SMat Martineau 		.retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
3892c20f8e35SMat Martineau 		.monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
3893c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
3894c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
3895c20f8e35SMat Martineau 	};
38960a708f8fSGustavo F. Padovan 
389747d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
38980a708f8fSGustavo F. Padovan 
38990c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
39000a708f8fSGustavo F. Padovan 		return;
39010a708f8fSGustavo F. Padovan 
39020a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
39030a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
39040a708f8fSGustavo F. Padovan 
3905c20f8e35SMat Martineau 		switch (type) {
3906c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
3907c20f8e35SMat Martineau 			if (olen == sizeof(rfc))
39080a708f8fSGustavo F. Padovan 				memcpy(&rfc, (void *)val, olen);
3909c20f8e35SMat Martineau 			break;
3910c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
3911c20f8e35SMat Martineau 			txwin_ext = val;
3912c20f8e35SMat Martineau 			break;
3913c20f8e35SMat Martineau 		}
39140a708f8fSGustavo F. Padovan 	}
39150a708f8fSGustavo F. Padovan 
39160a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
39170a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
391847d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
391947d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
392047d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
3921c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
3922c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
3923c20f8e35SMat Martineau 		else
3924c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
3925c20f8e35SMat Martineau 					      rfc.txwin_size);
39260a708f8fSGustavo F. Padovan 		break;
39270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
392847d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
39290a708f8fSGustavo F. Padovan 	}
39300a708f8fSGustavo F. Padovan }
39310a708f8fSGustavo F. Padovan 
39322d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
3933cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
3934cb3b3152SJohan Hedberg 				    u8 *data)
39350a708f8fSGustavo F. Padovan {
3936e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
39370a708f8fSGustavo F. Padovan 
3938cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
3939cb3b3152SJohan Hedberg 		return -EPROTO;
3940cb3b3152SJohan Hedberg 
3941e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
39420a708f8fSGustavo F. Padovan 		return 0;
39430a708f8fSGustavo F. Padovan 
39440a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
39450a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
394617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
39470a708f8fSGustavo F. Padovan 
39480a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
39490a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
39500a708f8fSGustavo F. Padovan 
39510a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
39520a708f8fSGustavo F. Padovan 	}
39530a708f8fSGustavo F. Padovan 
39540a708f8fSGustavo F. Padovan 	return 0;
39550a708f8fSGustavo F. Padovan }
39560a708f8fSGustavo F. Padovan 
39571700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
39581700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
39594c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
39600a708f8fSGustavo F. Padovan {
39610a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39620a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
396323691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
39640a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
39650a708f8fSGustavo F. Padovan 
39660a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
39670a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
39680a708f8fSGustavo F. Padovan 
3969097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
39700a708f8fSGustavo F. Padovan 
39710a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
39726f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
3973bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
397423691d75SGustavo F. Padovan 	if (!pchan) {
39750a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
39760a708f8fSGustavo F. Padovan 		goto sendresp;
39770a708f8fSGustavo F. Padovan 	}
39780a708f8fSGustavo F. Padovan 
39793df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
39808ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
39810a708f8fSGustavo F. Padovan 
39820a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
39832983fd68SAndrei Emeltchenko 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
39840a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
39859f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
39860a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
39870a708f8fSGustavo F. Padovan 		goto response;
39880a708f8fSGustavo F. Padovan 	}
39890a708f8fSGustavo F. Padovan 
39900a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
39910a708f8fSGustavo F. Padovan 
39922dfa1003SGustavo Padovan 	/* Check if we already have channel with that dcid */
39932dfa1003SGustavo Padovan 	if (__l2cap_get_chan_by_dcid(conn, scid))
39942dfa1003SGustavo Padovan 		goto response;
39952dfa1003SGustavo Padovan 
399680b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
399780808e43SGustavo F. Padovan 	if (!chan)
39980a708f8fSGustavo F. Padovan 		goto response;
39990a708f8fSGustavo F. Padovan 
4000330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
4001330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
4002330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
4003330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
4004330b6c15SSyam Sidhardhan 	 */
4005330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
4006330b6c15SSyam Sidhardhan 
40077eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
40087eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
40094f1654e0SMarcel Holtmann 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
40104f1654e0SMarcel Holtmann 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
4011fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
4012fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
40131700915fSMat Martineau 	chan->local_amp_id = amp_id;
40140a708f8fSGustavo F. Padovan 
40156be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
401648454079SGustavo F. Padovan 
4017fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
40180a708f8fSGustavo F. Padovan 
40198d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
40200a708f8fSGustavo F. Padovan 
4021fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
40220a708f8fSGustavo F. Padovan 
40230a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4024d45fc423SGustavo F. Padovan 		if (l2cap_chan_check_security(chan)) {
4025bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4026f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
40270a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
40280a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
40292dc4e510SGustavo Padovan 				chan->ops->defer(chan);
40300a708f8fSGustavo F. Padovan 			} else {
40311700915fSMat Martineau 				/* Force pending result for AMP controllers.
40321700915fSMat Martineau 				 * The connection will succeed after the
40331700915fSMat Martineau 				 * physical link is up.
40341700915fSMat Martineau 				 */
40356ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4036f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
40370a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
40386ed971caSMarcel Holtmann 				} else {
4039f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
40406ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
40411700915fSMat Martineau 				}
40420a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
40430a708f8fSGustavo F. Padovan 			}
40440a708f8fSGustavo F. Padovan 		} else {
4045f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
40460a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
40470a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
40480a708f8fSGustavo F. Padovan 		}
40490a708f8fSGustavo F. Padovan 	} else {
4050f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
40510a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
40520a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
40530a708f8fSGustavo F. Padovan 	}
40540a708f8fSGustavo F. Padovan 
40550a708f8fSGustavo F. Padovan response:
40568ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
40573df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
40580a708f8fSGustavo F. Padovan 
40590a708f8fSGustavo F. Padovan sendresp:
40600a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
40610a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
40620a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
40630a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
40644c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40650a708f8fSGustavo F. Padovan 
40660a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40670a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4068ac73498cSAndrei Emeltchenko 		info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
40690a708f8fSGustavo F. Padovan 
40700a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
40710a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
40720a708f8fSGustavo F. Padovan 
4073ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
40740a708f8fSGustavo F. Padovan 
40752d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
40762d792818SGustavo Padovan 			       sizeof(info), &info);
40770a708f8fSGustavo F. Padovan 	}
40780a708f8fSGustavo F. Padovan 
4079c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
40800a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
40810a708f8fSGustavo F. Padovan 		u8 buf[128];
4082c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
40830a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
408473ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
408573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
40860a708f8fSGustavo F. Padovan 	}
40871700915fSMat Martineau 
40881700915fSMat Martineau 	return chan;
40894c89b6aaSMat Martineau }
40900a708f8fSGustavo F. Padovan 
40914c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4092cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
40934c89b6aaSMat Martineau {
40947b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
40957b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
40967b064edaSJaganath Kanakkassery 
4097cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4098cb3b3152SJohan Hedberg 		return -EPROTO;
4099cb3b3152SJohan Hedberg 
41007b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
41017b064edaSJaganath Kanakkassery 	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
41027b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
41037b064edaSJaganath Kanakkassery 		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
41047b064edaSJaganath Kanakkassery 				      hcon->dst_type, 0, NULL, 0,
41057b064edaSJaganath Kanakkassery 				      hcon->dev_class);
41067b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
41077b064edaSJaganath Kanakkassery 
4108300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
41090a708f8fSGustavo F. Padovan 	return 0;
41100a708f8fSGustavo F. Padovan }
41110a708f8fSGustavo F. Padovan 
41125909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4113cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4114cb3b3152SJohan Hedberg 				    u8 *data)
41150a708f8fSGustavo F. Padovan {
41160a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
41170a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
411848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
41190a708f8fSGustavo F. Padovan 	u8 req[128];
41203df91ea2SAndrei Emeltchenko 	int err;
41210a708f8fSGustavo F. Padovan 
4122cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4123cb3b3152SJohan Hedberg 		return -EPROTO;
4124cb3b3152SJohan Hedberg 
41250a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
41260a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
41270a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
41280a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
41290a708f8fSGustavo F. Padovan 
41301b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
41311b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
41320a708f8fSGustavo F. Padovan 
41333df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41343df91ea2SAndrei Emeltchenko 
41350a708f8fSGustavo F. Padovan 	if (scid) {
41363df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
41373df91ea2SAndrei Emeltchenko 		if (!chan) {
413821870b52SJohan Hedberg 			err = -EBADSLT;
41393df91ea2SAndrei Emeltchenko 			goto unlock;
41403df91ea2SAndrei Emeltchenko 		}
41410a708f8fSGustavo F. Padovan 	} else {
41423df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
41433df91ea2SAndrei Emeltchenko 		if (!chan) {
414421870b52SJohan Hedberg 			err = -EBADSLT;
41453df91ea2SAndrei Emeltchenko 			goto unlock;
41463df91ea2SAndrei Emeltchenko 		}
41470a708f8fSGustavo F. Padovan 	}
41480a708f8fSGustavo F. Padovan 
41493df91ea2SAndrei Emeltchenko 	err = 0;
41503df91ea2SAndrei Emeltchenko 
41516be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
415248454079SGustavo F. Padovan 
41530a708f8fSGustavo F. Padovan 	switch (result) {
41540a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
415589bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4156fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4157fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4158c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
41590a708f8fSGustavo F. Padovan 
4160c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
41610a708f8fSGustavo F. Padovan 			break;
41620a708f8fSGustavo F. Padovan 
41630a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
416473ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, req), req);
416573ffa904SGustavo F. Padovan 		chan->num_conf_req++;
41660a708f8fSGustavo F. Padovan 		break;
41670a708f8fSGustavo F. Padovan 
41680a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4169c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
41700a708f8fSGustavo F. Padovan 		break;
41710a708f8fSGustavo F. Padovan 
41720a708f8fSGustavo F. Padovan 	default:
417348454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
41740a708f8fSGustavo F. Padovan 		break;
41750a708f8fSGustavo F. Padovan 	}
41760a708f8fSGustavo F. Padovan 
41776be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
41783df91ea2SAndrei Emeltchenko 
41793df91ea2SAndrei Emeltchenko unlock:
41803df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
41813df91ea2SAndrei Emeltchenko 
41823df91ea2SAndrei Emeltchenko 	return err;
41830a708f8fSGustavo F. Padovan }
41840a708f8fSGustavo F. Padovan 
418547d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
41860a708f8fSGustavo F. Padovan {
41870a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
41880a708f8fSGustavo F. Padovan 	 * sides request it.
41890a708f8fSGustavo F. Padovan 	 */
41900c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
419147d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4192f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
419347d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
41940a708f8fSGustavo F. Padovan }
41950a708f8fSGustavo F. Padovan 
419629d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
419729d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
419829d8a590SAndrei Emeltchenko {
419929d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
420029d8a590SAndrei Emeltchenko 
420129d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
420229d8a590SAndrei Emeltchenko 	       flags);
420329d8a590SAndrei Emeltchenko 
420429d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
420529d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
420629d8a590SAndrei Emeltchenko 
420729d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
420829d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
420929d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
421029d8a590SAndrei Emeltchenko }
421129d8a590SAndrei Emeltchenko 
4212662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4213662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4214662d652dSJohan Hedberg {
4215662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4216662d652dSJohan Hedberg 
4217662d652dSJohan Hedberg 	rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
4218662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4219662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4220662d652dSJohan Hedberg 
4221662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4222662d652dSJohan Hedberg }
4223662d652dSJohan Hedberg 
42242d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
42252d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
42262d792818SGustavo Padovan 				   u8 *data)
42270a708f8fSGustavo F. Padovan {
42280a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
42290a708f8fSGustavo F. Padovan 	u16 dcid, flags;
42300a708f8fSGustavo F. Padovan 	u8 rsp[64];
423148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42323c588192SMat Martineau 	int len, err = 0;
42330a708f8fSGustavo F. Padovan 
4234cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4235cb3b3152SJohan Hedberg 		return -EPROTO;
4236cb3b3152SJohan Hedberg 
42370a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
42380a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
42390a708f8fSGustavo F. Padovan 
42400a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
42410a708f8fSGustavo F. Padovan 
4242baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4243662d652dSJohan Hedberg 	if (!chan) {
4244662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4245662d652dSJohan Hedberg 		return 0;
4246662d652dSJohan Hedberg 	}
42470a708f8fSGustavo F. Padovan 
4248033b1142SDavid S. Miller 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
4249662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4250662d652dSJohan Hedberg 				       chan->dcid);
42510a708f8fSGustavo F. Padovan 		goto unlock;
42520a708f8fSGustavo F. Padovan 	}
42530a708f8fSGustavo F. Padovan 
42540a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
42550a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4256cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
42570a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4258fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42590a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
42600a708f8fSGustavo F. Padovan 		goto unlock;
42610a708f8fSGustavo F. Padovan 	}
42620a708f8fSGustavo F. Padovan 
42630a708f8fSGustavo F. Padovan 	/* Store config. */
426473ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
426573ffa904SGustavo F. Padovan 	chan->conf_len += len;
42660a708f8fSGustavo F. Padovan 
426759e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
42680a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
42690a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4270fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
42715325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
42720a708f8fSGustavo F. Padovan 		goto unlock;
42730a708f8fSGustavo F. Padovan 	}
42740a708f8fSGustavo F. Padovan 
42750a708f8fSGustavo F. Padovan 	/* Complete config. */
427673ffa904SGustavo F. Padovan 	len = l2cap_parse_conf_req(chan, rsp);
42770a708f8fSGustavo F. Padovan 	if (len < 0) {
42785e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
42790a708f8fSGustavo F. Padovan 		goto unlock;
42800a708f8fSGustavo F. Padovan 	}
42810a708f8fSGustavo F. Padovan 
42821500109bSMat Martineau 	chan->ident = cmd->ident;
42830a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
428473ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
42850a708f8fSGustavo F. Padovan 
42860a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
428773ffa904SGustavo F. Padovan 	chan->conf_len = 0;
42880a708f8fSGustavo F. Padovan 
4289c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
42900a708f8fSGustavo F. Padovan 		goto unlock;
42910a708f8fSGustavo F. Padovan 
4292c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
429347d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
42940a708f8fSGustavo F. Padovan 
4295105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4296105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
42973c588192SMat Martineau 			err = l2cap_ertm_init(chan);
42980a708f8fSGustavo F. Padovan 
42993c588192SMat Martineau 		if (err < 0)
43005e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
43013c588192SMat Martineau 		else
4302cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
43033c588192SMat Martineau 
43040a708f8fSGustavo F. Padovan 		goto unlock;
43050a708f8fSGustavo F. Padovan 	}
43060a708f8fSGustavo F. Padovan 
4307c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
43080a708f8fSGustavo F. Padovan 		u8 buf[64];
43090a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
431073ffa904SGustavo F. Padovan 			       l2cap_build_conf_req(chan, buf), buf);
431173ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43120a708f8fSGustavo F. Padovan 	}
43130a708f8fSGustavo F. Padovan 
43140e8b207eSAndrei Emeltchenko 	/* Got Conf Rsp PENDING from remote side and asume we sent
43150e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
43160e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
43170e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43180e8b207eSAndrei Emeltchenko 
43190e8b207eSAndrei Emeltchenko 		/* check compatibility */
43200e8b207eSAndrei Emeltchenko 
432179de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4322f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
432329d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
432479de886dSAndrei Emeltchenko 		else
432579de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
43260e8b207eSAndrei Emeltchenko 	}
43270e8b207eSAndrei Emeltchenko 
43280a708f8fSGustavo F. Padovan unlock:
43296be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43303c588192SMat Martineau 	return err;
43310a708f8fSGustavo F. Padovan }
43320a708f8fSGustavo F. Padovan 
43332d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4334cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4335cb3b3152SJohan Hedberg 				   u8 *data)
43360a708f8fSGustavo F. Padovan {
43370a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
43380a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
433948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4340cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
43413c588192SMat Martineau 	int err = 0;
43420a708f8fSGustavo F. Padovan 
4343cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4344cb3b3152SJohan Hedberg 		return -EPROTO;
4345cb3b3152SJohan Hedberg 
43460a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
43470a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
43480a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
43490a708f8fSGustavo F. Padovan 
435061386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
435161386cbaSAndrei Emeltchenko 	       result, len);
43520a708f8fSGustavo F. Padovan 
4353baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
435448454079SGustavo F. Padovan 	if (!chan)
43550a708f8fSGustavo F. Padovan 		return 0;
43560a708f8fSGustavo F. Padovan 
43570a708f8fSGustavo F. Padovan 	switch (result) {
43580a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
435947d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
43600e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43610a708f8fSGustavo F. Padovan 		break;
43620a708f8fSGustavo F. Padovan 
43630e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
43640e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
43650e8b207eSAndrei Emeltchenko 
43660e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
43670e8b207eSAndrei Emeltchenko 			char buf[64];
43680e8b207eSAndrei Emeltchenko 
43690e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
43700e8b207eSAndrei Emeltchenko 						   buf, &result);
43710e8b207eSAndrei Emeltchenko 			if (len < 0) {
43725e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43730e8b207eSAndrei Emeltchenko 				goto done;
43740e8b207eSAndrei Emeltchenko 			}
43750e8b207eSAndrei Emeltchenko 
4376f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
437779de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
437879de886dSAndrei Emeltchenko 							0);
43795ce66b59SAndrei Emeltchenko 			} else {
43805ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
43815ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
438279de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
43830e8b207eSAndrei Emeltchenko 				}
43845ce66b59SAndrei Emeltchenko 			}
43855ce66b59SAndrei Emeltchenko 		}
43860e8b207eSAndrei Emeltchenko 		goto done;
43870e8b207eSAndrei Emeltchenko 
43880a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
438973ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
43900a708f8fSGustavo F. Padovan 			char req[64];
43910a708f8fSGustavo F. Padovan 
43920a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
43935e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
43940a708f8fSGustavo F. Padovan 				goto done;
43950a708f8fSGustavo F. Padovan 			}
43960a708f8fSGustavo F. Padovan 
43970a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
43980a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4399b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4400b4450035SGustavo F. Padovan 						   req, &result);
44010a708f8fSGustavo F. Padovan 			if (len < 0) {
44025e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
44030a708f8fSGustavo F. Padovan 				goto done;
44040a708f8fSGustavo F. Padovan 			}
44050a708f8fSGustavo F. Padovan 
44060a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
44070a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
440873ffa904SGustavo F. Padovan 			chan->num_conf_req++;
44090a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
44100a708f8fSGustavo F. Padovan 				goto done;
44110a708f8fSGustavo F. Padovan 			break;
44120a708f8fSGustavo F. Padovan 		}
44130a708f8fSGustavo F. Padovan 
44140a708f8fSGustavo F. Padovan 	default:
44156be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
44162e0052e4SAndrei Emeltchenko 
4417ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
44185e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
44190a708f8fSGustavo F. Padovan 		goto done;
44200a708f8fSGustavo F. Padovan 	}
44210a708f8fSGustavo F. Padovan 
442259e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
44230a708f8fSGustavo F. Padovan 		goto done;
44240a708f8fSGustavo F. Padovan 
4425c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
44260a708f8fSGustavo F. Padovan 
4427c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
442847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44290a708f8fSGustavo F. Padovan 
4430105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4431105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44323c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44330a708f8fSGustavo F. Padovan 
44343c588192SMat Martineau 		if (err < 0)
44355e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44363c588192SMat Martineau 		else
4437cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44380a708f8fSGustavo F. Padovan 	}
44390a708f8fSGustavo F. Padovan 
44400a708f8fSGustavo F. Padovan done:
44416be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44423c588192SMat Martineau 	return err;
44430a708f8fSGustavo F. Padovan }
44440a708f8fSGustavo F. Padovan 
44452d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4446cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4447cb3b3152SJohan Hedberg 				       u8 *data)
44480a708f8fSGustavo F. Padovan {
44490a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
44500a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
44510a708f8fSGustavo F. Padovan 	u16 dcid, scid;
445248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44530a708f8fSGustavo F. Padovan 
4454cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4455cb3b3152SJohan Hedberg 		return -EPROTO;
4456cb3b3152SJohan Hedberg 
44570a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
44580a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
44590a708f8fSGustavo F. Padovan 
44600a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
44610a708f8fSGustavo F. Padovan 
44623df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
44633df91ea2SAndrei Emeltchenko 
44643df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
44653df91ea2SAndrei Emeltchenko 	if (!chan) {
44663df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4467662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4468662d652dSJohan Hedberg 		return 0;
44693df91ea2SAndrei Emeltchenko 	}
44700a708f8fSGustavo F. Padovan 
44716be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
44726be36555SAndrei Emeltchenko 
4473fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4474fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
44750a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
44760a708f8fSGustavo F. Padovan 
44775ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
44780a708f8fSGustavo F. Padovan 
447961d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
448048454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
44816be36555SAndrei Emeltchenko 
44826be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44830a708f8fSGustavo F. Padovan 
448480b98027SGustavo Padovan 	chan->ops->close(chan);
448561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
44863df91ea2SAndrei Emeltchenko 
44873df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
44883df91ea2SAndrei Emeltchenko 
44890a708f8fSGustavo F. Padovan 	return 0;
44900a708f8fSGustavo F. Padovan }
44910a708f8fSGustavo F. Padovan 
44922d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4493cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4494cb3b3152SJohan Hedberg 				       u8 *data)
44950a708f8fSGustavo F. Padovan {
44960a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
44970a708f8fSGustavo F. Padovan 	u16 dcid, scid;
449848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44990a708f8fSGustavo F. Padovan 
4500cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4501cb3b3152SJohan Hedberg 		return -EPROTO;
4502cb3b3152SJohan Hedberg 
45030a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
45040a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
45050a708f8fSGustavo F. Padovan 
45060a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
45070a708f8fSGustavo F. Padovan 
45083df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
45093df91ea2SAndrei Emeltchenko 
45103df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
45113df91ea2SAndrei Emeltchenko 	if (!chan) {
45123df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
45130a708f8fSGustavo F. Padovan 		return 0;
45143df91ea2SAndrei Emeltchenko 	}
45150a708f8fSGustavo F. Padovan 
45166be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
451748454079SGustavo F. Padovan 
451861d6ef3eSMat Martineau 	l2cap_chan_hold(chan);
451948454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
45206be36555SAndrei Emeltchenko 
45216be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45220a708f8fSGustavo F. Padovan 
452380b98027SGustavo Padovan 	chan->ops->close(chan);
452461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
45253df91ea2SAndrei Emeltchenko 
45263df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
45273df91ea2SAndrei Emeltchenko 
45280a708f8fSGustavo F. Padovan 	return 0;
45290a708f8fSGustavo F. Padovan }
45300a708f8fSGustavo F. Padovan 
45312d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4532cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4533cb3b3152SJohan Hedberg 					u8 *data)
45340a708f8fSGustavo F. Padovan {
45350a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
45360a708f8fSGustavo F. Padovan 	u16 type;
45370a708f8fSGustavo F. Padovan 
4538cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4539cb3b3152SJohan Hedberg 		return -EPROTO;
4540cb3b3152SJohan Hedberg 
45410a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
45420a708f8fSGustavo F. Padovan 
45430a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
45440a708f8fSGustavo F. Padovan 
45450a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
45460a708f8fSGustavo F. Padovan 		u8 buf[8];
45470a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
45480a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4549ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK);
4550ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
45510a708f8fSGustavo F. Padovan 		if (!disable_ertm)
45520a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
45530a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
4554848566b3SMarcel Holtmann 		if (conn->hs_enabled)
45556327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
45566327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4557a5fd6f30SAndrei Emeltchenko 
45580a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
45592d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45602d792818SGustavo Padovan 			       buf);
45610a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
45620a708f8fSGustavo F. Padovan 		u8 buf[12];
45630a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
456450a147cdSMat Martineau 
4565848566b3SMarcel Holtmann 		if (conn->hs_enabled)
456650a147cdSMat Martineau 			l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
456750a147cdSMat Martineau 		else
456850a147cdSMat Martineau 			l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
456950a147cdSMat Martineau 
4570ac73498cSAndrei Emeltchenko 		rsp->type   = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4571ac73498cSAndrei Emeltchenko 		rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS);
4572c6337ea6SAndrei Emeltchenko 		memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
45732d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
45742d792818SGustavo Padovan 			       buf);
45750a708f8fSGustavo F. Padovan 	} else {
45760a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
45770a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4578ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP);
45792d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
45802d792818SGustavo Padovan 			       &rsp);
45810a708f8fSGustavo F. Padovan 	}
45820a708f8fSGustavo F. Padovan 
45830a708f8fSGustavo F. Padovan 	return 0;
45840a708f8fSGustavo F. Padovan }
45850a708f8fSGustavo F. Padovan 
45862d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4587cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4588cb3b3152SJohan Hedberg 					u8 *data)
45890a708f8fSGustavo F. Padovan {
45900a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
45910a708f8fSGustavo F. Padovan 	u16 type, result;
45920a708f8fSGustavo F. Padovan 
45933f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4594cb3b3152SJohan Hedberg 		return -EPROTO;
4595cb3b3152SJohan Hedberg 
45960a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
45970a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
45980a708f8fSGustavo F. Padovan 
45990a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
46000a708f8fSGustavo F. Padovan 
4601e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4602e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4603e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4604e90165beSAndrei Emeltchenko 		return 0;
4605e90165beSAndrei Emeltchenko 
460617cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
46070a708f8fSGustavo F. Padovan 
46080a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
46090a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46100a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46110a708f8fSGustavo F. Padovan 
46120a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
46130a708f8fSGustavo F. Padovan 
46140a708f8fSGustavo F. Padovan 		return 0;
46150a708f8fSGustavo F. Padovan 	}
46160a708f8fSGustavo F. Padovan 
4617978c93b9SAndrei Emeltchenko 	switch (type) {
4618978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
46190a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
46200a708f8fSGustavo F. Padovan 
46210a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
46220a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4623ac73498cSAndrei Emeltchenko 			req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN);
46240a708f8fSGustavo F. Padovan 
46250a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
46260a708f8fSGustavo F. Padovan 
46270a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
46280a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
46290a708f8fSGustavo F. Padovan 		} else {
46300a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46310a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
46320a708f8fSGustavo F. Padovan 
46330a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
46340a708f8fSGustavo F. Padovan 		}
4635978c93b9SAndrei Emeltchenko 		break;
4636978c93b9SAndrei Emeltchenko 
4637978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
4638978c93b9SAndrei Emeltchenko 		conn->fixed_chan_mask = rsp->data[0];
46390a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
46400a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
46410a708f8fSGustavo F. Padovan 
46420a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4643978c93b9SAndrei Emeltchenko 		break;
46440a708f8fSGustavo F. Padovan 	}
46450a708f8fSGustavo F. Padovan 
46460a708f8fSGustavo F. Padovan 	return 0;
46470a708f8fSGustavo F. Padovan }
46480a708f8fSGustavo F. Padovan 
46491700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
46502d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
46512d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4652f94ff6ffSMat Martineau {
4653f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
46546e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
46551700915fSMat Martineau 	struct l2cap_chan *chan;
46566e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4657f94ff6ffSMat Martineau 	u16 psm, scid;
4658f94ff6ffSMat Martineau 
4659f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4660f94ff6ffSMat Martineau 		return -EPROTO;
4661f94ff6ffSMat Martineau 
4662848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
4663f94ff6ffSMat Martineau 		return -EINVAL;
4664f94ff6ffSMat Martineau 
4665f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4666f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4667f94ff6ffSMat Martineau 
4668ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4669f94ff6ffSMat Martineau 
46706e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
46716ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
46726e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46736e1df6a6SAndrei Emeltchenko 			      req->amp_id);
46746e1df6a6SAndrei Emeltchenko 		return 0;
46756e1df6a6SAndrei Emeltchenko 	}
46761700915fSMat Martineau 
46771700915fSMat Martineau 	/* Validate AMP controller id */
46781700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
46796e1df6a6SAndrei Emeltchenko 	if (!hdev)
46806e1df6a6SAndrei Emeltchenko 		goto error;
46811700915fSMat Martineau 
46826e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
46836e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
46846e1df6a6SAndrei Emeltchenko 		goto error;
46856e1df6a6SAndrei Emeltchenko 	}
46866e1df6a6SAndrei Emeltchenko 
46876e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
46886e1df6a6SAndrei Emeltchenko 			     req->amp_id);
46896e1df6a6SAndrei Emeltchenko 	if (chan) {
46906e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
46916e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
46926e1df6a6SAndrei Emeltchenko 
469398e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
469498e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
46956e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
46966e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4697662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4698662d652dSJohan Hedberg 					       chan->dcid);
4699662d652dSJohan Hedberg 			return 0;
47006e1df6a6SAndrei Emeltchenko 		}
47016e1df6a6SAndrei Emeltchenko 
47026e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
47036e1df6a6SAndrei Emeltchenko 
47046e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
47056e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4706fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
47076e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
47086e1df6a6SAndrei Emeltchenko 	}
47096e1df6a6SAndrei Emeltchenko 
47106e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
47116e1df6a6SAndrei Emeltchenko 
47126e1df6a6SAndrei Emeltchenko 	return 0;
47136e1df6a6SAndrei Emeltchenko 
47146e1df6a6SAndrei Emeltchenko error:
4715f94ff6ffSMat Martineau 	rsp.dcid = 0;
4716f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
47171700915fSMat Martineau 	rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP);
47188ce0c498SAndrei Emeltchenko 	rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
4719f94ff6ffSMat Martineau 
4720f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4721f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4722f94ff6ffSMat Martineau 
4723dc280801SJohan Hedberg 	return 0;
4724f94ff6ffSMat Martineau }
4725f94ff6ffSMat Martineau 
47268eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
47278eb200bdSMat Martineau {
47288eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
47298eb200bdSMat Martineau 	u8 ident;
47308eb200bdSMat Martineau 
47318eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
47328eb200bdSMat Martineau 
47338eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
47348eb200bdSMat Martineau 	chan->ident = ident;
47358eb200bdSMat Martineau 
47368eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
47378eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
47388eb200bdSMat Martineau 
47398eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
47408eb200bdSMat Martineau 		       &req);
47418eb200bdSMat Martineau 
47428eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47438eb200bdSMat Martineau }
47448eb200bdSMat Martineau 
47451500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
47468d5a04a1SMat Martineau {
47478d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
47488d5a04a1SMat Martineau 
47491500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47508d5a04a1SMat Martineau 
47511500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
47528d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
47538d5a04a1SMat Martineau 
47541500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
47551500109bSMat Martineau 		       sizeof(rsp), &rsp);
47568d5a04a1SMat Martineau }
47578d5a04a1SMat Martineau 
47585b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
47598d5a04a1SMat Martineau {
47608d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47618d5a04a1SMat Martineau 
47625b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
47638d5a04a1SMat Martineau 
47645b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
47658d5a04a1SMat Martineau 
47665b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
47678d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
47688d5a04a1SMat Martineau 
47695b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
47705b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47715b155ef9SMat Martineau 
47725b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
47735b155ef9SMat Martineau }
47745b155ef9SMat Martineau 
47755b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
47765b155ef9SMat Martineau {
47775b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
47785b155ef9SMat Martineau 
47795b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
47805b155ef9SMat Martineau 
47815b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
47825b155ef9SMat Martineau 	cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED);
47835b155ef9SMat Martineau 
47845b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
47855b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
47868d5a04a1SMat Martineau }
47878d5a04a1SMat Martineau 
47888d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
47898d5a04a1SMat Martineau 					 u16 icid)
47908d5a04a1SMat Martineau {
47918d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
47928d5a04a1SMat Martineau 
4793ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
47948d5a04a1SMat Martineau 
47958d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
47968d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
47978d5a04a1SMat Martineau }
47988d5a04a1SMat Martineau 
47995f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
48005f3847a4SMat Martineau {
48015f3847a4SMat Martineau 	chan->hs_hchan = NULL;
48025f3847a4SMat Martineau 	chan->hs_hcon = NULL;
48035f3847a4SMat Martineau 
48045f3847a4SMat Martineau 	/* Placeholder - release the logical link */
48055f3847a4SMat Martineau }
48065f3847a4SMat Martineau 
48071500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
48081500109bSMat Martineau {
48091500109bSMat Martineau 	/* Logical link setup failed */
48101500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
48111500109bSMat Martineau 		/* Create channel failure, disconnect */
48125e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
48131500109bSMat Martineau 		return;
48141500109bSMat Martineau 	}
48151500109bSMat Martineau 
48161500109bSMat Martineau 	switch (chan->move_role) {
48171500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
48181500109bSMat Martineau 		l2cap_move_done(chan);
48191500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
48201500109bSMat Martineau 		break;
48211500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
48221500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
48231500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
48241500109bSMat Martineau 			/* Remote has only sent pending or
48251500109bSMat Martineau 			 * success responses, clean up
48261500109bSMat Martineau 			 */
48271500109bSMat Martineau 			l2cap_move_done(chan);
48281500109bSMat Martineau 		}
48291500109bSMat Martineau 
48301500109bSMat Martineau 		/* Other amp move states imply that the move
48311500109bSMat Martineau 		 * has already aborted
48321500109bSMat Martineau 		 */
48331500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
48341500109bSMat Martineau 		break;
48351500109bSMat Martineau 	}
48361500109bSMat Martineau }
48371500109bSMat Martineau 
48381500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
48391500109bSMat Martineau 					struct hci_chan *hchan)
48401500109bSMat Martineau {
48411500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
48421500109bSMat Martineau 
4843336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
48441500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48451500109bSMat Martineau 
484635ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
48471500109bSMat Martineau 
48481500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4849fe79c6feSAndrei Emeltchenko 		int err;
48501500109bSMat Martineau 
48511500109bSMat Martineau 		set_default_fcs(chan);
48521500109bSMat Martineau 
48531500109bSMat Martineau 		err = l2cap_ertm_init(chan);
48541500109bSMat Martineau 		if (err < 0)
48555e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
48561500109bSMat Martineau 		else
48571500109bSMat Martineau 			l2cap_chan_ready(chan);
48581500109bSMat Martineau 	}
48591500109bSMat Martineau }
48601500109bSMat Martineau 
48611500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
48621500109bSMat Martineau 				      struct hci_chan *hchan)
48631500109bSMat Martineau {
48641500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
48651500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
48661500109bSMat Martineau 
48671500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
48681500109bSMat Martineau 
48691500109bSMat Martineau 	switch (chan->move_state) {
48701500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
48711500109bSMat Martineau 		/* Move confirm will be sent after a success
48721500109bSMat Martineau 		 * response is received
48731500109bSMat Martineau 		 */
48741500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
48751500109bSMat Martineau 		break;
48761500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
48771500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
48781500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
48791500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
48801500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
48811500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
48821500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
48831500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
48841500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
48851500109bSMat Martineau 		}
48861500109bSMat Martineau 		break;
48871500109bSMat Martineau 	default:
48881500109bSMat Martineau 		/* Move was not in expected state, free the channel */
48891500109bSMat Martineau 		__release_logical_link(chan);
48901500109bSMat Martineau 
48911500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
48921500109bSMat Martineau 	}
48931500109bSMat Martineau }
48941500109bSMat Martineau 
48951500109bSMat Martineau /* Call with chan locked */
489627695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
48975b155ef9SMat Martineau 		       u8 status)
48985b155ef9SMat Martineau {
48991500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
49001500109bSMat Martineau 
49011500109bSMat Martineau 	if (status) {
49021500109bSMat Martineau 		l2cap_logical_fail(chan);
49031500109bSMat Martineau 		__release_logical_link(chan);
49045b155ef9SMat Martineau 		return;
49055b155ef9SMat Martineau 	}
49065b155ef9SMat Martineau 
49071500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
49081500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
49096ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
49101500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
49111500109bSMat Martineau 	} else {
49121500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
49131500109bSMat Martineau 	}
49141500109bSMat Martineau }
49151500109bSMat Martineau 
49163f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
49173f7a56c4SMat Martineau {
49183f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
49193f7a56c4SMat Martineau 
49206ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
49213f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
49223f7a56c4SMat Martineau 			return;
49233f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49243f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
49253f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
49263f7a56c4SMat Martineau 	} else {
49273f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
49283f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
49293f7a56c4SMat Martineau 		chan->move_id = 0;
49303f7a56c4SMat Martineau 		l2cap_move_setup(chan);
49313f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
49323f7a56c4SMat Martineau 	}
49333f7a56c4SMat Martineau }
49343f7a56c4SMat Martineau 
49358eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
49368eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
49378eb200bdSMat Martineau {
493862748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
493962748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
494062748ca1SAndrei Emeltchenko 
494112d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
494212d6cc60SAndrei Emeltchenko 
494362748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
494462748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
494562748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
494662748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
494762748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
494862748ca1SAndrei Emeltchenko 		} else {
494962748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
495062748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
495162748ca1SAndrei Emeltchenko 		}
495262748ca1SAndrei Emeltchenko 
495362748ca1SAndrei Emeltchenko 		return;
495462748ca1SAndrei Emeltchenko 	}
495562748ca1SAndrei Emeltchenko 
495662748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
495762748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
49588eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
49598eb200bdSMat Martineau 		char buf[128];
49608eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
49618eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
49628eb200bdSMat Martineau 
49638eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
49648eb200bdSMat Martineau 			/* Send successful response */
496562cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
496662cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49678eb200bdSMat Martineau 		} else {
49688eb200bdSMat Martineau 			/* Send negative response */
496962cd50e2SAndrei Emeltchenko 			rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM);
497062cd50e2SAndrei Emeltchenko 			rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
49718eb200bdSMat Martineau 		}
49728eb200bdSMat Martineau 
49738eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
49748eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
49758eb200bdSMat Martineau 
49768eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
4977f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
49788eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
49798eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
49808eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
49818eb200bdSMat Martineau 				       l2cap_build_conf_req(chan, buf), buf);
49828eb200bdSMat Martineau 			chan->num_conf_req++;
49838eb200bdSMat Martineau 		}
49848eb200bdSMat Martineau 	}
49858eb200bdSMat Martineau }
49868eb200bdSMat Martineau 
49878eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
49888eb200bdSMat Martineau 				   u8 remote_amp_id)
49898eb200bdSMat Martineau {
49908eb200bdSMat Martineau 	l2cap_move_setup(chan);
49918eb200bdSMat Martineau 	chan->move_id = local_amp_id;
49928eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
49938eb200bdSMat Martineau 
49948eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
49958eb200bdSMat Martineau }
49968eb200bdSMat Martineau 
49978eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
49988eb200bdSMat Martineau {
49998eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
50008eb200bdSMat Martineau 
50018eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
50028eb200bdSMat Martineau 
50038eb200bdSMat Martineau 	if (hchan) {
50048eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
50058eb200bdSMat Martineau 			/* Logical link is ready to go */
50068eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
50078eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
50088eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
50098eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
50108eb200bdSMat Martineau 
50118eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
50128eb200bdSMat Martineau 		} else {
50138eb200bdSMat Martineau 			/* Wait for logical link to be ready */
50148eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
50158eb200bdSMat Martineau 		}
50168eb200bdSMat Martineau 	} else {
50178eb200bdSMat Martineau 		/* Logical link not available */
50188eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
50198eb200bdSMat Martineau 	}
50208eb200bdSMat Martineau }
50218eb200bdSMat Martineau 
50228eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
50238eb200bdSMat Martineau {
50248eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50258eb200bdSMat Martineau 		u8 rsp_result;
50268eb200bdSMat Martineau 		if (result == -EINVAL)
50278eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
50288eb200bdSMat Martineau 		else
50298eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
50308eb200bdSMat Martineau 
50318eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
50328eb200bdSMat Martineau 	}
50338eb200bdSMat Martineau 
50348eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
50358eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
50368eb200bdSMat Martineau 
50378eb200bdSMat Martineau 	/* Restart data transmission */
50388eb200bdSMat Martineau 	l2cap_ertm_send(chan);
50398eb200bdSMat Martineau }
50408eb200bdSMat Martineau 
5041a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5042a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
50438eb200bdSMat Martineau {
5044770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5045fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5046770bfefaSAndrei Emeltchenko 
50478eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
50488eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
50498eb200bdSMat Martineau 
50508eb200bdSMat Martineau 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED) {
50518eb200bdSMat Martineau 		l2cap_chan_unlock(chan);
50528eb200bdSMat Martineau 		return;
50538eb200bdSMat Martineau 	}
50548eb200bdSMat Martineau 
50558eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
50568eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
50578eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
50588eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
50598eb200bdSMat Martineau 	} else {
50608eb200bdSMat Martineau 		switch (chan->move_role) {
50618eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
50628eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
50638eb200bdSMat Martineau 					       remote_amp_id);
50648eb200bdSMat Martineau 			break;
50658eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
50668eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
50678eb200bdSMat Martineau 			break;
50688eb200bdSMat Martineau 		default:
50698eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
50708eb200bdSMat Martineau 			break;
50718eb200bdSMat Martineau 		}
50728eb200bdSMat Martineau 	}
50738eb200bdSMat Martineau }
50748eb200bdSMat Martineau 
50758d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5076ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5077ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
50788d5a04a1SMat Martineau {
50798d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
50801500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
508102b0fbb9SMat Martineau 	struct l2cap_chan *chan;
50828d5a04a1SMat Martineau 	u16 icid = 0;
50838d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
50848d5a04a1SMat Martineau 
50858d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
50868d5a04a1SMat Martineau 		return -EPROTO;
50878d5a04a1SMat Martineau 
50888d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
50898d5a04a1SMat Martineau 
5090ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
50918d5a04a1SMat Martineau 
5092848566b3SMarcel Holtmann 	if (!conn->hs_enabled)
50938d5a04a1SMat Martineau 		return -EINVAL;
50948d5a04a1SMat Martineau 
509502b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
509602b0fbb9SMat Martineau 	if (!chan) {
50971500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
50981500109bSMat Martineau 		rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
50991500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
51001500109bSMat Martineau 			       sizeof(rsp), &rsp);
510102b0fbb9SMat Martineau 		return 0;
510202b0fbb9SMat Martineau 	}
510302b0fbb9SMat Martineau 
51041500109bSMat Martineau 	chan->ident = cmd->ident;
51051500109bSMat Martineau 
510602b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
510702b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
510802b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
510902b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
511002b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
511102b0fbb9SMat Martineau 		goto send_move_response;
511202b0fbb9SMat Martineau 	}
511302b0fbb9SMat Martineau 
511402b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
511502b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
511602b0fbb9SMat Martineau 		goto send_move_response;
511702b0fbb9SMat Martineau 	}
511802b0fbb9SMat Martineau 
51196ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
512002b0fbb9SMat Martineau 		struct hci_dev *hdev;
512102b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
512202b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
512302b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
512402b0fbb9SMat Martineau 			if (hdev)
512502b0fbb9SMat Martineau 				hci_dev_put(hdev);
512602b0fbb9SMat Martineau 
512702b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
512802b0fbb9SMat Martineau 			goto send_move_response;
512902b0fbb9SMat Martineau 		}
513002b0fbb9SMat Martineau 		hci_dev_put(hdev);
513102b0fbb9SMat Martineau 	}
513202b0fbb9SMat Martineau 
513302b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
513402b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
513502b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
513602b0fbb9SMat Martineau 	 */
513702b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
513802b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
51396f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
514002b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
514102b0fbb9SMat Martineau 		goto send_move_response;
514202b0fbb9SMat Martineau 	}
514302b0fbb9SMat Martineau 
514402b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
514502b0fbb9SMat Martineau 	l2cap_move_setup(chan);
514602b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
514702b0fbb9SMat Martineau 	icid = chan->dcid;
514802b0fbb9SMat Martineau 
51496ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
515002b0fbb9SMat Martineau 		/* Moving to BR/EDR */
515102b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
515202b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
515302b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
515402b0fbb9SMat Martineau 		} else {
515502b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
515602b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
515702b0fbb9SMat Martineau 		}
515802b0fbb9SMat Martineau 	} else {
515902b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
516002b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
516102b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
516202b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
516302b0fbb9SMat Martineau 	}
516402b0fbb9SMat Martineau 
516502b0fbb9SMat Martineau send_move_response:
51661500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
51678d5a04a1SMat Martineau 
516802b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
516902b0fbb9SMat Martineau 
51708d5a04a1SMat Martineau 	return 0;
51718d5a04a1SMat Martineau }
51728d5a04a1SMat Martineau 
51735b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
51745b155ef9SMat Martineau {
51755b155ef9SMat Martineau 	struct l2cap_chan *chan;
51765b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
51775b155ef9SMat Martineau 
51785b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
51795b155ef9SMat Martineau 	if (!chan) {
51805b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
51815b155ef9SMat Martineau 		return;
51825b155ef9SMat Martineau 	}
51835b155ef9SMat Martineau 
51845b155ef9SMat Martineau 	__clear_chan_timer(chan);
51855b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
51865b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
51875b155ef9SMat Martineau 
51885b155ef9SMat Martineau 	switch (chan->move_state) {
51895b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
51905b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
51915b155ef9SMat Martineau 		 * is complete.
51925b155ef9SMat Martineau 		 */
51935b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51945b155ef9SMat Martineau 		break;
51955b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
51965b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
51975b155ef9SMat Martineau 			break;
51985b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
51995b155ef9SMat Martineau 				    &chan->conn_state)) {
52005b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
52015b155ef9SMat Martineau 		} else {
52025b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
52035b155ef9SMat Martineau 			 * proceed with move
52045b155ef9SMat Martineau 			 */
52055b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
52065b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
52075b155ef9SMat Martineau 		}
52085b155ef9SMat Martineau 		break;
52095b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
52105b155ef9SMat Martineau 		/* Moving to AMP */
52115b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
52125b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
52135b155ef9SMat Martineau 			 * after logical link is ready
52145b155ef9SMat Martineau 			 */
52155b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
52165b155ef9SMat Martineau 		} else {
52175b155ef9SMat Martineau 			/* Both logical link and move success
52185b155ef9SMat Martineau 			 * are required to confirm
52195b155ef9SMat Martineau 			 */
52205b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
52215b155ef9SMat Martineau 		}
52225b155ef9SMat Martineau 
52235b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
52245b155ef9SMat Martineau 		if (!hchan) {
52255b155ef9SMat Martineau 			/* Logical link not available */
52265b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52275b155ef9SMat Martineau 			break;
52285b155ef9SMat Martineau 		}
52295b155ef9SMat Martineau 
52305b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
52315b155ef9SMat Martineau 		 * send confirmation.
52325b155ef9SMat Martineau 		 */
52335b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
52345b155ef9SMat Martineau 			break;
52355b155ef9SMat Martineau 
52365b155ef9SMat Martineau 		/* Logical link is already ready to go */
52375b155ef9SMat Martineau 
52385b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
52395b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
52405b155ef9SMat Martineau 
52415b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
52425b155ef9SMat Martineau 			/* Can confirm now */
52435b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
52445b155ef9SMat Martineau 		} else {
52455b155ef9SMat Martineau 			/* Now only need move success
52465b155ef9SMat Martineau 			 * to confirm
52475b155ef9SMat Martineau 			 */
52485b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
52495b155ef9SMat Martineau 		}
52505b155ef9SMat Martineau 
52515b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
52525b155ef9SMat Martineau 		break;
52535b155ef9SMat Martineau 	default:
52545b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
52555b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
52565b155ef9SMat Martineau 		l2cap_move_done(chan);
52575b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52585b155ef9SMat Martineau 	}
52595b155ef9SMat Martineau 
52605b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52615b155ef9SMat Martineau }
52625b155ef9SMat Martineau 
52635b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
52645b155ef9SMat Martineau 			    u16 result)
52655b155ef9SMat Martineau {
52665b155ef9SMat Martineau 	struct l2cap_chan *chan;
52675b155ef9SMat Martineau 
52685b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
52695b155ef9SMat Martineau 	if (!chan) {
52705b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
52715b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
52725b155ef9SMat Martineau 		return;
52735b155ef9SMat Martineau 	}
52745b155ef9SMat Martineau 
52755b155ef9SMat Martineau 	__clear_chan_timer(chan);
52765b155ef9SMat Martineau 
52775b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
52785b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
52795b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
52805b155ef9SMat Martineau 		} else {
52815b155ef9SMat Martineau 			/* Cleanup - cancel move */
52825b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
52835b155ef9SMat Martineau 			l2cap_move_done(chan);
52845b155ef9SMat Martineau 		}
52855b155ef9SMat Martineau 	}
52865b155ef9SMat Martineau 
52875b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
52885b155ef9SMat Martineau 
52895b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
52905b155ef9SMat Martineau }
52915b155ef9SMat Martineau 
52925b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5293ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5294ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
52958d5a04a1SMat Martineau {
52968d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
52978d5a04a1SMat Martineau 	u16 icid, result;
52988d5a04a1SMat Martineau 
52998d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
53008d5a04a1SMat Martineau 		return -EPROTO;
53018d5a04a1SMat Martineau 
53028d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
53038d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
53048d5a04a1SMat Martineau 
5305ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
53068d5a04a1SMat Martineau 
53075b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
53085b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
53095b155ef9SMat Martineau 	else
53105b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
53118d5a04a1SMat Martineau 
53128d5a04a1SMat Martineau 	return 0;
53138d5a04a1SMat Martineau }
53148d5a04a1SMat Martineau 
53155f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5316ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5317ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
53188d5a04a1SMat Martineau {
53198d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
53205f3847a4SMat Martineau 	struct l2cap_chan *chan;
53218d5a04a1SMat Martineau 	u16 icid, result;
53228d5a04a1SMat Martineau 
53238d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
53248d5a04a1SMat Martineau 		return -EPROTO;
53258d5a04a1SMat Martineau 
53268d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
53278d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
53288d5a04a1SMat Martineau 
5329ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
53308d5a04a1SMat Martineau 
53315f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
53325f3847a4SMat Martineau 	if (!chan) {
53335f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
53348d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53355f3847a4SMat Martineau 		return 0;
53365f3847a4SMat Martineau 	}
53375f3847a4SMat Martineau 
53385f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
53395f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
53405f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
53416ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
53425f3847a4SMat Martineau 				__release_logical_link(chan);
53435f3847a4SMat Martineau 		} else {
53445f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
53455f3847a4SMat Martineau 		}
53465f3847a4SMat Martineau 
53475f3847a4SMat Martineau 		l2cap_move_done(chan);
53485f3847a4SMat Martineau 	}
53495f3847a4SMat Martineau 
53505f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
53515f3847a4SMat Martineau 
53525f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
53538d5a04a1SMat Martineau 
53548d5a04a1SMat Martineau 	return 0;
53558d5a04a1SMat Martineau }
53568d5a04a1SMat Martineau 
53578d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5358ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5359ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
53608d5a04a1SMat Martineau {
53618d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
53623fd71a0aSMat Martineau 	struct l2cap_chan *chan;
53638d5a04a1SMat Martineau 	u16 icid;
53648d5a04a1SMat Martineau 
53658d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
53668d5a04a1SMat Martineau 		return -EPROTO;
53678d5a04a1SMat Martineau 
53688d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
53698d5a04a1SMat Martineau 
5370ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
53718d5a04a1SMat Martineau 
53723fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53733fd71a0aSMat Martineau 	if (!chan)
53743fd71a0aSMat Martineau 		return 0;
53753fd71a0aSMat Martineau 
53763fd71a0aSMat Martineau 	__clear_chan_timer(chan);
53773fd71a0aSMat Martineau 
53783fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
53793fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
53803fd71a0aSMat Martineau 
53816ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
53823fd71a0aSMat Martineau 			__release_logical_link(chan);
53833fd71a0aSMat Martineau 
53843fd71a0aSMat Martineau 		l2cap_move_done(chan);
53853fd71a0aSMat Martineau 	}
53863fd71a0aSMat Martineau 
53873fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
53883fd71a0aSMat Martineau 
53898d5a04a1SMat Martineau 	return 0;
53908d5a04a1SMat Martineau }
53918d5a04a1SMat Martineau 
5392e2174ca4SGustavo F. Padovan static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
5393de73115aSClaudio Takahasi 					 u16 to_multiplier)
5394de73115aSClaudio Takahasi {
5395de73115aSClaudio Takahasi 	u16 max_latency;
5396de73115aSClaudio Takahasi 
5397de73115aSClaudio Takahasi 	if (min > max || min < 6 || max > 3200)
5398de73115aSClaudio Takahasi 		return -EINVAL;
5399de73115aSClaudio Takahasi 
5400de73115aSClaudio Takahasi 	if (to_multiplier < 10 || to_multiplier > 3200)
5401de73115aSClaudio Takahasi 		return -EINVAL;
5402de73115aSClaudio Takahasi 
5403de73115aSClaudio Takahasi 	if (max >= to_multiplier * 8)
5404de73115aSClaudio Takahasi 		return -EINVAL;
5405de73115aSClaudio Takahasi 
5406de73115aSClaudio Takahasi 	max_latency = (to_multiplier * 8 / max) - 1;
5407de73115aSClaudio Takahasi 	if (latency > 499 || latency > max_latency)
5408de73115aSClaudio Takahasi 		return -EINVAL;
5409de73115aSClaudio Takahasi 
5410de73115aSClaudio Takahasi 	return 0;
5411de73115aSClaudio Takahasi }
5412de73115aSClaudio Takahasi 
5413de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
54142d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5415203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5416de73115aSClaudio Takahasi {
5417de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5418de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5419de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5420203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
54212ce603ebSClaudio Takahasi 	int err;
5422de73115aSClaudio Takahasi 
5423de73115aSClaudio Takahasi 	if (!(hcon->link_mode & HCI_LM_MASTER))
5424de73115aSClaudio Takahasi 		return -EINVAL;
5425de73115aSClaudio Takahasi 
5426de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5427de73115aSClaudio Takahasi 		return -EPROTO;
5428de73115aSClaudio Takahasi 
5429de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5430de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5431de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5432de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5433de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5434de73115aSClaudio Takahasi 
5435de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5436de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5437de73115aSClaudio Takahasi 
5438de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
54392ce603ebSClaudio Takahasi 
54402ce603ebSClaudio Takahasi 	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
54412ce603ebSClaudio Takahasi 	if (err)
5442ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5443de73115aSClaudio Takahasi 	else
5444ac73498cSAndrei Emeltchenko 		rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5445de73115aSClaudio Takahasi 
5446de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5447de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5448de73115aSClaudio Takahasi 
54492ce603ebSClaudio Takahasi 	if (!err)
54502ce603ebSClaudio Takahasi 		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
54512ce603ebSClaudio Takahasi 
5452de73115aSClaudio Takahasi 	return 0;
5453de73115aSClaudio Takahasi }
5454de73115aSClaudio Takahasi 
5455f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5456f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5457f1496deeSJohan Hedberg 				u8 *data)
5458f1496deeSJohan Hedberg {
5459f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
5460f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5461f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
5462f1496deeSJohan Hedberg 	int err;
5463f1496deeSJohan Hedberg 
5464f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5465f1496deeSJohan Hedberg 		return -EPROTO;
5466f1496deeSJohan Hedberg 
5467f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5468f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5469f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5470f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5471f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5472f1496deeSJohan Hedberg 
5473f1496deeSJohan Hedberg 	if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
5474f1496deeSJohan Hedberg 		return -EPROTO;
5475f1496deeSJohan Hedberg 
5476f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5477f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5478f1496deeSJohan Hedberg 
5479f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5480f1496deeSJohan Hedberg 
5481f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5482f1496deeSJohan Hedberg 	if (!chan) {
5483f1496deeSJohan Hedberg 		err = -EBADSLT;
5484f1496deeSJohan Hedberg 		goto unlock;
5485f1496deeSJohan Hedberg 	}
5486f1496deeSJohan Hedberg 
5487f1496deeSJohan Hedberg 	err = 0;
5488f1496deeSJohan Hedberg 
5489f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5490f1496deeSJohan Hedberg 
5491f1496deeSJohan Hedberg 	switch (result) {
5492f1496deeSJohan Hedberg 	case L2CAP_CR_SUCCESS:
5493f1496deeSJohan Hedberg 		chan->ident = 0;
5494f1496deeSJohan Hedberg 		chan->dcid = dcid;
5495f1496deeSJohan Hedberg 		chan->omtu = mtu;
5496f1496deeSJohan Hedberg 		chan->remote_mps = mps;
54970cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5498f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5499f1496deeSJohan Hedberg 		break;
5500f1496deeSJohan Hedberg 
5501f1496deeSJohan Hedberg 	default:
5502f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5503f1496deeSJohan Hedberg 		break;
5504f1496deeSJohan Hedberg 	}
5505f1496deeSJohan Hedberg 
5506f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5507f1496deeSJohan Hedberg 
5508f1496deeSJohan Hedberg unlock:
5509f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5510f1496deeSJohan Hedberg 
5511f1496deeSJohan Hedberg 	return err;
5512f1496deeSJohan Hedberg }
5513f1496deeSJohan Hedberg 
55143300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
55152d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
55162d792818SGustavo Padovan 				      u8 *data)
55173300d9a9SClaudio Takahasi {
55183300d9a9SClaudio Takahasi 	int err = 0;
55193300d9a9SClaudio Takahasi 
55203300d9a9SClaudio Takahasi 	switch (cmd->code) {
55213300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5522cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
55233300d9a9SClaudio Takahasi 		break;
55243300d9a9SClaudio Takahasi 
55253300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5526cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
55273300d9a9SClaudio Takahasi 		break;
55283300d9a9SClaudio Takahasi 
55293300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5530f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
55319245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
55323300d9a9SClaudio Takahasi 		break;
55333300d9a9SClaudio Takahasi 
55343300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
55353300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
55363300d9a9SClaudio Takahasi 		break;
55373300d9a9SClaudio Takahasi 
55383300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
55399245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
55403300d9a9SClaudio Takahasi 		break;
55413300d9a9SClaudio Takahasi 
55423300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5543cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
55443300d9a9SClaudio Takahasi 		break;
55453300d9a9SClaudio Takahasi 
55463300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
55479245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
55483300d9a9SClaudio Takahasi 		break;
55493300d9a9SClaudio Takahasi 
55503300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
55513300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
55523300d9a9SClaudio Takahasi 		break;
55533300d9a9SClaudio Takahasi 
55543300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
55553300d9a9SClaudio Takahasi 		break;
55563300d9a9SClaudio Takahasi 
55573300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5558cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
55593300d9a9SClaudio Takahasi 		break;
55603300d9a9SClaudio Takahasi 
55613300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
55629245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
55633300d9a9SClaudio Takahasi 		break;
55643300d9a9SClaudio Takahasi 
5565f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5566f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5567f94ff6ffSMat Martineau 		break;
5568f94ff6ffSMat Martineau 
55698d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
55708d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
55718d5a04a1SMat Martineau 		break;
55728d5a04a1SMat Martineau 
55738d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
55749245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
55758d5a04a1SMat Martineau 		break;
55768d5a04a1SMat Martineau 
55778d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
55788d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
55798d5a04a1SMat Martineau 		break;
55808d5a04a1SMat Martineau 
55818d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
55829245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
55838d5a04a1SMat Martineau 		break;
55848d5a04a1SMat Martineau 
55853300d9a9SClaudio Takahasi 	default:
55863300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
55873300d9a9SClaudio Takahasi 		err = -EINVAL;
55883300d9a9SClaudio Takahasi 		break;
55893300d9a9SClaudio Takahasi 	}
55903300d9a9SClaudio Takahasi 
55913300d9a9SClaudio Takahasi 	return err;
55923300d9a9SClaudio Takahasi }
55933300d9a9SClaudio Takahasi 
559427e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
559527e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
559627e2d4c8SJohan Hedberg 				u8 *data)
559727e2d4c8SJohan Hedberg {
559827e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
559927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
560027e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
56010cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
560227e2d4c8SJohan Hedberg 	__le16 psm;
560327e2d4c8SJohan Hedberg 	u8 result;
560427e2d4c8SJohan Hedberg 
560527e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
560627e2d4c8SJohan Hedberg 		return -EPROTO;
560727e2d4c8SJohan Hedberg 
560827e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
560927e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
561027e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
561127e2d4c8SJohan Hedberg 	psm  = req->psm;
561227e2d4c8SJohan Hedberg 	dcid = 0;
56130cd75f7eSJohan Hedberg 	credits = 0;
561427e2d4c8SJohan Hedberg 
561527e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
561627e2d4c8SJohan Hedberg 		return -EPROTO;
561727e2d4c8SJohan Hedberg 
561827e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
561927e2d4c8SJohan Hedberg 	       scid, mtu, mps);
562027e2d4c8SJohan Hedberg 
562127e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
562227e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
562327e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
562427e2d4c8SJohan Hedberg 	if (!pchan) {
562527e2d4c8SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
562627e2d4c8SJohan Hedberg 		chan = NULL;
562727e2d4c8SJohan Hedberg 		goto response;
562827e2d4c8SJohan Hedberg 	}
562927e2d4c8SJohan Hedberg 
563027e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
563127e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
563227e2d4c8SJohan Hedberg 
563327e2d4c8SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
563427e2d4c8SJohan Hedberg 		result = L2CAP_CR_AUTHENTICATION;
563527e2d4c8SJohan Hedberg 		chan = NULL;
563627e2d4c8SJohan Hedberg 		goto response_unlock;
563727e2d4c8SJohan Hedberg 	}
563827e2d4c8SJohan Hedberg 
563927e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
564027e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
564127e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
564227e2d4c8SJohan Hedberg 		chan = NULL;
564327e2d4c8SJohan Hedberg 		goto response_unlock;
564427e2d4c8SJohan Hedberg 	}
564527e2d4c8SJohan Hedberg 
564627e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
564727e2d4c8SJohan Hedberg 	if (!chan) {
564827e2d4c8SJohan Hedberg 		result = L2CAP_CR_NO_MEM;
564927e2d4c8SJohan Hedberg 		goto response_unlock;
565027e2d4c8SJohan Hedberg 	}
565127e2d4c8SJohan Hedberg 
565227e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
565327e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
565427e2d4c8SJohan Hedberg 	chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
565527e2d4c8SJohan Hedberg 	chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
565627e2d4c8SJohan Hedberg 	chan->psm  = psm;
565727e2d4c8SJohan Hedberg 	chan->dcid = scid;
565827e2d4c8SJohan Hedberg 	chan->omtu = mtu;
565927e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
56600cd75f7eSJohan Hedberg 	chan->tx_credits = __le16_to_cpu(req->credits);
566127e2d4c8SJohan Hedberg 
566227e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
566327e2d4c8SJohan Hedberg 	dcid = chan->scid;
56640cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
566527e2d4c8SJohan Hedberg 
566627e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
566727e2d4c8SJohan Hedberg 
566827e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
566927e2d4c8SJohan Hedberg 
567027e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
567127e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
567227e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
567327e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
567427e2d4c8SJohan Hedberg 	} else {
567527e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
567627e2d4c8SJohan Hedberg 		result = L2CAP_CR_SUCCESS;
567727e2d4c8SJohan Hedberg 	}
567827e2d4c8SJohan Hedberg 
567927e2d4c8SJohan Hedberg response_unlock:
568027e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
568127e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
568227e2d4c8SJohan Hedberg 
568327e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
568427e2d4c8SJohan Hedberg 		return 0;
568527e2d4c8SJohan Hedberg 
568627e2d4c8SJohan Hedberg response:
568727e2d4c8SJohan Hedberg 	if (chan) {
568827e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
56893916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
569027e2d4c8SJohan Hedberg 	} else {
569127e2d4c8SJohan Hedberg 		rsp.mtu = 0;
569227e2d4c8SJohan Hedberg 		rsp.mps = 0;
569327e2d4c8SJohan Hedberg 	}
569427e2d4c8SJohan Hedberg 
569527e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
56960cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
569727e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
569827e2d4c8SJohan Hedberg 
569927e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
570027e2d4c8SJohan Hedberg 
570127e2d4c8SJohan Hedberg 	return 0;
570227e2d4c8SJohan Hedberg }
570327e2d4c8SJohan Hedberg 
5704fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5705fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5706fad5fc89SJohan Hedberg 				   u8 *data)
5707fad5fc89SJohan Hedberg {
5708fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5709fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
5710fad5fc89SJohan Hedberg 	u16 cid, credits;
5711fad5fc89SJohan Hedberg 
5712fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5713fad5fc89SJohan Hedberg 		return -EPROTO;
5714fad5fc89SJohan Hedberg 
5715fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5716fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5717fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5718fad5fc89SJohan Hedberg 
5719fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5720fad5fc89SJohan Hedberg 
5721fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5722fad5fc89SJohan Hedberg 	if (!chan)
5723fad5fc89SJohan Hedberg 		return -EBADSLT;
5724fad5fc89SJohan Hedberg 
5725fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5726fad5fc89SJohan Hedberg 
5727fad5fc89SJohan Hedberg 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
5728fad5fc89SJohan Hedberg 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
5729fad5fc89SJohan Hedberg 		chan->tx_credits--;
5730fad5fc89SJohan Hedberg 	}
5731fad5fc89SJohan Hedberg 
5732fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5733fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5734fad5fc89SJohan Hedberg 
5735fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5736fad5fc89SJohan Hedberg 
5737fad5fc89SJohan Hedberg 	return 0;
5738fad5fc89SJohan Hedberg }
5739fad5fc89SJohan Hedberg 
57403300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5741203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5742203e639eSJohan Hedberg 				   u8 *data)
57433300d9a9SClaudio Takahasi {
5744b5ecba64SJohan Hedberg 	int err = 0;
5745b5ecba64SJohan Hedberg 
57463af8ace6SJohan Hedberg 	if (!enable_lecoc) {
57473af8ace6SJohan Hedberg 		switch (cmd->code) {
57483af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_REQ:
57493af8ace6SJohan Hedberg 		case L2CAP_LE_CONN_RSP:
57503af8ace6SJohan Hedberg 		case L2CAP_LE_CREDITS:
57513af8ace6SJohan Hedberg 		case L2CAP_DISCONN_REQ:
57523af8ace6SJohan Hedberg 		case L2CAP_DISCONN_RSP:
57533af8ace6SJohan Hedberg 			return -EINVAL;
57543af8ace6SJohan Hedberg 		}
57553af8ace6SJohan Hedberg 	}
57563af8ace6SJohan Hedberg 
57573300d9a9SClaudio Takahasi 	switch (cmd->code) {
57583300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5759b5ecba64SJohan Hedberg 		break;
57603300d9a9SClaudio Takahasi 
57613300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
5762b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
5763b5ecba64SJohan Hedberg 		break;
57643300d9a9SClaudio Takahasi 
57653300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
5766b5ecba64SJohan Hedberg 		break;
57673300d9a9SClaudio Takahasi 
5768f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
5769f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
5770b5ecba64SJohan Hedberg 		break;
5771f1496deeSJohan Hedberg 
577227e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
5773b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
5774b5ecba64SJohan Hedberg 		break;
577527e2d4c8SJohan Hedberg 
5776fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
5777fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
5778fad5fc89SJohan Hedberg 		break;
5779fad5fc89SJohan Hedberg 
57803defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
5781b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
5782b5ecba64SJohan Hedberg 		break;
57833defe01aSJohan Hedberg 
57843defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
57853defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
5786b5ecba64SJohan Hedberg 		break;
57873defe01aSJohan Hedberg 
57883300d9a9SClaudio Takahasi 	default:
57893300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
5790b5ecba64SJohan Hedberg 		err = -EINVAL;
5791b5ecba64SJohan Hedberg 		break;
57923300d9a9SClaudio Takahasi 	}
5793b5ecba64SJohan Hedberg 
5794b5ecba64SJohan Hedberg 	return err;
57953300d9a9SClaudio Takahasi }
57963300d9a9SClaudio Takahasi 
5797c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
5798c5623556SJohan Hedberg 					struct sk_buff *skb)
5799c5623556SJohan Hedberg {
580069c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
58014f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
58024f3e219dSMarcel Holtmann 	u16 len;
5803c5623556SJohan Hedberg 	int err;
5804c5623556SJohan Hedberg 
580569c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
58063b166295SMarcel Holtmann 		goto drop;
580769c4e4e8SJohan Hedberg 
58084f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
58094f3e219dSMarcel Holtmann 		goto drop;
5810c5623556SJohan Hedberg 
58114f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
58124f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
5813c5623556SJohan Hedberg 
58144f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
5815c5623556SJohan Hedberg 
58164f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
58174f3e219dSMarcel Holtmann 
58184f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
5819c5623556SJohan Hedberg 		BT_DBG("corrupted command");
58204f3e219dSMarcel Holtmann 		goto drop;
5821c5623556SJohan Hedberg 	}
5822c5623556SJohan Hedberg 
5823203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
5824c5623556SJohan Hedberg 	if (err) {
5825c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
5826c5623556SJohan Hedberg 
5827c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
5828c5623556SJohan Hedberg 
5829a521149aSJohan Hedberg 		rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58304f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
5831c5623556SJohan Hedberg 			       sizeof(rej), &rej);
5832c5623556SJohan Hedberg 	}
5833c5623556SJohan Hedberg 
58343b166295SMarcel Holtmann drop:
5835c5623556SJohan Hedberg 	kfree_skb(skb);
5836c5623556SJohan Hedberg }
5837c5623556SJohan Hedberg 
58383300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
58393300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
58400a708f8fSGustavo F. Padovan {
584169c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
58420a708f8fSGustavo F. Padovan 	u8 *data = skb->data;
58430a708f8fSGustavo F. Padovan 	int len = skb->len;
58440a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr cmd;
58453300d9a9SClaudio Takahasi 	int err;
58460a708f8fSGustavo F. Padovan 
58470a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
58480a708f8fSGustavo F. Padovan 
584969c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
58503b166295SMarcel Holtmann 		goto drop;
585169c4e4e8SJohan Hedberg 
58520a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CMD_HDR_SIZE) {
58530a708f8fSGustavo F. Padovan 		u16 cmd_len;
58540a708f8fSGustavo F. Padovan 		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
58550a708f8fSGustavo F. Padovan 		data += L2CAP_CMD_HDR_SIZE;
58560a708f8fSGustavo F. Padovan 		len  -= L2CAP_CMD_HDR_SIZE;
58570a708f8fSGustavo F. Padovan 
58580a708f8fSGustavo F. Padovan 		cmd_len = le16_to_cpu(cmd.len);
58590a708f8fSGustavo F. Padovan 
58602d792818SGustavo Padovan 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len,
58612d792818SGustavo Padovan 		       cmd.ident);
58620a708f8fSGustavo F. Padovan 
58630a708f8fSGustavo F. Padovan 		if (cmd_len > len || !cmd.ident) {
58640a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
58650a708f8fSGustavo F. Padovan 			break;
58660a708f8fSGustavo F. Padovan 		}
58670a708f8fSGustavo F. Padovan 
58683300d9a9SClaudio Takahasi 		err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
58690a708f8fSGustavo F. Padovan 		if (err) {
5870e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
58712c6d1a2eSGustavo F. Padovan 
58722c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
58730a708f8fSGustavo F. Padovan 
5874a521149aSJohan Hedberg 			rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
58752d792818SGustavo Padovan 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
58762d792818SGustavo Padovan 				       sizeof(rej), &rej);
58770a708f8fSGustavo F. Padovan 		}
58780a708f8fSGustavo F. Padovan 
58790a708f8fSGustavo F. Padovan 		data += cmd_len;
58800a708f8fSGustavo F. Padovan 		len  -= cmd_len;
58810a708f8fSGustavo F. Padovan 	}
58820a708f8fSGustavo F. Padovan 
58833b166295SMarcel Holtmann drop:
58840a708f8fSGustavo F. Padovan 	kfree_skb(skb);
58850a708f8fSGustavo F. Padovan }
58860a708f8fSGustavo F. Padovan 
588747d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
58880a708f8fSGustavo F. Padovan {
58890a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
5890e4ca6d98SAndrei Emeltchenko 	int hdr_size;
5891e4ca6d98SAndrei Emeltchenko 
5892e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
5893e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
5894e4ca6d98SAndrei Emeltchenko 	else
5895e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
58960a708f8fSGustavo F. Padovan 
589747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
589803a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
58990a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
59000a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
59010a708f8fSGustavo F. Padovan 
59020a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
59030a708f8fSGustavo F. Padovan 			return -EBADMSG;
59040a708f8fSGustavo F. Padovan 	}
59050a708f8fSGustavo F. Padovan 	return 0;
59060a708f8fSGustavo F. Padovan }
59070a708f8fSGustavo F. Padovan 
59086ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
59090a708f8fSGustavo F. Padovan {
5910e31f7633SMat Martineau 	struct l2cap_ctrl control;
59110a708f8fSGustavo F. Padovan 
5912e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
59130a708f8fSGustavo F. Padovan 
5914e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
5915e31f7633SMat Martineau 	control.sframe = 1;
5916e31f7633SMat Martineau 	control.final = 1;
5917e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
5918e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
59190a708f8fSGustavo F. Padovan 
5920e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
5921e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
5922e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59230a708f8fSGustavo F. Padovan 	}
59240a708f8fSGustavo F. Padovan 
5925e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
5926e31f7633SMat Martineau 	    chan->unacked_frames > 0)
5927e31f7633SMat Martineau 		__set_retrans_timer(chan);
59280a708f8fSGustavo F. Padovan 
5929e31f7633SMat Martineau 	/* Send pending iframes */
5930525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
59310a708f8fSGustavo F. Padovan 
5932e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
5933e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
5934e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
5935e31f7633SMat Martineau 		 * send it now.
5936e31f7633SMat Martineau 		 */
5937e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
5938e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
59390a708f8fSGustavo F. Padovan 	}
59400a708f8fSGustavo F. Padovan }
59410a708f8fSGustavo F. Padovan 
59422d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
59432d792818SGustavo Padovan 			    struct sk_buff **last_frag)
59440a708f8fSGustavo F. Padovan {
594584084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
594684084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
594784084a31SMat Martineau 	 */
594884084a31SMat Martineau 	if (!skb_has_frag_list(skb))
594984084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
595084084a31SMat Martineau 
595184084a31SMat Martineau 	new_frag->next = NULL;
595284084a31SMat Martineau 
595384084a31SMat Martineau 	(*last_frag)->next = new_frag;
595484084a31SMat Martineau 	*last_frag = new_frag;
595584084a31SMat Martineau 
595684084a31SMat Martineau 	skb->len += new_frag->len;
595784084a31SMat Martineau 	skb->data_len += new_frag->len;
595884084a31SMat Martineau 	skb->truesize += new_frag->truesize;
595984084a31SMat Martineau }
596084084a31SMat Martineau 
59614b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
59624b51dae9SMat Martineau 				struct l2cap_ctrl *control)
596384084a31SMat Martineau {
596484084a31SMat Martineau 	int err = -EINVAL;
59650a708f8fSGustavo F. Padovan 
59664b51dae9SMat Martineau 	switch (control->sar) {
59677e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
596884084a31SMat Martineau 		if (chan->sdu)
596984084a31SMat Martineau 			break;
59700a708f8fSGustavo F. Padovan 
597180b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
597284084a31SMat Martineau 		break;
59730a708f8fSGustavo F. Padovan 
59747e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
597584084a31SMat Martineau 		if (chan->sdu)
597684084a31SMat Martineau 			break;
59770a708f8fSGustavo F. Padovan 
59786f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
597903a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
59800a708f8fSGustavo F. Padovan 
598184084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
598284084a31SMat Martineau 			err = -EMSGSIZE;
598384084a31SMat Martineau 			break;
598484084a31SMat Martineau 		}
59850a708f8fSGustavo F. Padovan 
598684084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
598784084a31SMat Martineau 			break;
598884084a31SMat Martineau 
598984084a31SMat Martineau 		chan->sdu = skb;
599084084a31SMat Martineau 		chan->sdu_last_frag = skb;
599184084a31SMat Martineau 
599284084a31SMat Martineau 		skb = NULL;
599384084a31SMat Martineau 		err = 0;
59940a708f8fSGustavo F. Padovan 		break;
59950a708f8fSGustavo F. Padovan 
59967e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
59976f61fd47SGustavo F. Padovan 		if (!chan->sdu)
599884084a31SMat Martineau 			break;
59990a708f8fSGustavo F. Padovan 
600084084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
600184084a31SMat Martineau 				&chan->sdu_last_frag);
600284084a31SMat Martineau 		skb = NULL;
60030a708f8fSGustavo F. Padovan 
600484084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
600584084a31SMat Martineau 			break;
60060a708f8fSGustavo F. Padovan 
600784084a31SMat Martineau 		err = 0;
60080a708f8fSGustavo F. Padovan 		break;
60090a708f8fSGustavo F. Padovan 
60107e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
60116f61fd47SGustavo F. Padovan 		if (!chan->sdu)
601284084a31SMat Martineau 			break;
60130a708f8fSGustavo F. Padovan 
601484084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
601584084a31SMat Martineau 				&chan->sdu_last_frag);
601684084a31SMat Martineau 		skb = NULL;
60170a708f8fSGustavo F. Padovan 
601884084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
601984084a31SMat Martineau 			break;
60200a708f8fSGustavo F. Padovan 
602180b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
60220a708f8fSGustavo F. Padovan 
602384084a31SMat Martineau 		if (!err) {
602484084a31SMat Martineau 			/* Reassembly complete */
602584084a31SMat Martineau 			chan->sdu = NULL;
602684084a31SMat Martineau 			chan->sdu_last_frag = NULL;
602784084a31SMat Martineau 			chan->sdu_len = 0;
60280a708f8fSGustavo F. Padovan 		}
60290a708f8fSGustavo F. Padovan 		break;
60300a708f8fSGustavo F. Padovan 	}
60310a708f8fSGustavo F. Padovan 
603284084a31SMat Martineau 	if (err) {
60330a708f8fSGustavo F. Padovan 		kfree_skb(skb);
60346f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
60356f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
603684084a31SMat Martineau 		chan->sdu_last_frag = NULL;
603784084a31SMat Martineau 		chan->sdu_len = 0;
603884084a31SMat Martineau 	}
60390a708f8fSGustavo F. Padovan 
604084084a31SMat Martineau 	return err;
60410a708f8fSGustavo F. Padovan }
60420a708f8fSGustavo F. Padovan 
604332b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
604432b32735SMat Martineau {
604532b32735SMat Martineau 	/* Placeholder */
604632b32735SMat Martineau 	return 0;
604732b32735SMat Martineau }
604832b32735SMat Martineau 
6049e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
60500a708f8fSGustavo F. Padovan {
605161aa4f5bSMat Martineau 	u8 event;
605261aa4f5bSMat Martineau 
605361aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
605461aa4f5bSMat Martineau 		return;
605561aa4f5bSMat Martineau 
605661aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6057401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
60580a708f8fSGustavo F. Padovan }
60590a708f8fSGustavo F. Padovan 
6060d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6061d2a7ac5dSMat Martineau {
606263838725SMat Martineau 	int err = 0;
606363838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
606463838725SMat Martineau 	 * until a gap is encountered.
606563838725SMat Martineau 	 */
606663838725SMat Martineau 
606763838725SMat Martineau 	BT_DBG("chan %p", chan);
606863838725SMat Martineau 
606963838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
607063838725SMat Martineau 		struct sk_buff *skb;
607163838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
607263838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
607363838725SMat Martineau 
607463838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
607563838725SMat Martineau 
607663838725SMat Martineau 		if (!skb)
607763838725SMat Martineau 			break;
607863838725SMat Martineau 
607963838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
608063838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
608163838725SMat Martineau 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->control);
608263838725SMat Martineau 		if (err)
608363838725SMat Martineau 			break;
608463838725SMat Martineau 	}
608563838725SMat Martineau 
608663838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
608763838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
608863838725SMat Martineau 		l2cap_send_ack(chan);
608963838725SMat Martineau 	}
609063838725SMat Martineau 
609163838725SMat Martineau 	return err;
6092d2a7ac5dSMat Martineau }
6093d2a7ac5dSMat Martineau 
6094d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6095d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6096d2a7ac5dSMat Martineau {
6097f80842a8SMat Martineau 	struct sk_buff *skb;
6098f80842a8SMat Martineau 
6099f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6100f80842a8SMat Martineau 
6101f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6102f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61035e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6104f80842a8SMat Martineau 		return;
6105f80842a8SMat Martineau 	}
6106f80842a8SMat Martineau 
6107f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6108f80842a8SMat Martineau 
6109f80842a8SMat Martineau 	if (skb == NULL) {
6110f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6111f80842a8SMat Martineau 		       control->reqseq);
6112f80842a8SMat Martineau 		return;
6113f80842a8SMat Martineau 	}
6114f80842a8SMat Martineau 
6115f80842a8SMat Martineau 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
6116f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61175e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6118f80842a8SMat Martineau 		return;
6119f80842a8SMat Martineau 	}
6120f80842a8SMat Martineau 
6121f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6122f80842a8SMat Martineau 
6123f80842a8SMat Martineau 	if (control->poll) {
6124f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6125f80842a8SMat Martineau 
6126f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6127f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6128f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6129f80842a8SMat Martineau 
6130f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6131f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6132f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6133f80842a8SMat Martineau 		}
6134f80842a8SMat Martineau 	} else {
6135f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6136f80842a8SMat Martineau 
6137f80842a8SMat Martineau 		if (control->final) {
6138f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6139f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6140f80842a8SMat Martineau 						&chan->conn_state))
6141f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6142f80842a8SMat Martineau 		} else {
6143f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6144f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6145f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6146f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6147f80842a8SMat Martineau 			}
6148f80842a8SMat Martineau 		}
6149f80842a8SMat Martineau 	}
6150d2a7ac5dSMat Martineau }
6151d2a7ac5dSMat Martineau 
6152d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6153d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6154d2a7ac5dSMat Martineau {
6155fcd289dfSMat Martineau 	struct sk_buff *skb;
6156fcd289dfSMat Martineau 
6157fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6158fcd289dfSMat Martineau 
6159fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6160fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
61615e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6162fcd289dfSMat Martineau 		return;
6163fcd289dfSMat Martineau 	}
6164fcd289dfSMat Martineau 
6165fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6166fcd289dfSMat Martineau 
6167fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6168fcd289dfSMat Martineau 	    bt_cb(skb)->control.retries >= chan->max_tx) {
6169fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
61705e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6171fcd289dfSMat Martineau 		return;
6172fcd289dfSMat Martineau 	}
6173fcd289dfSMat Martineau 
6174fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6175fcd289dfSMat Martineau 
6176fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6177fcd289dfSMat Martineau 
6178fcd289dfSMat Martineau 	if (control->final) {
6179fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6180fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6181fcd289dfSMat Martineau 	} else {
6182fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6183fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6184fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6185fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6186fcd289dfSMat Martineau 	}
6187d2a7ac5dSMat Martineau }
6188d2a7ac5dSMat Martineau 
61894b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
61904b51dae9SMat Martineau {
61914b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
61924b51dae9SMat Martineau 
61934b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
61944b51dae9SMat Martineau 	       chan->expected_tx_seq);
61954b51dae9SMat Martineau 
61964b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
61974b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
61984b51dae9SMat Martineau 		    chan->tx_win) {
61994b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
62004b51dae9SMat Martineau 			 * invalid packets.
62014b51dae9SMat Martineau 			 */
62024b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62034b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
62044b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
62054b51dae9SMat Martineau 			} else {
62064b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
62074b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
62084b51dae9SMat Martineau 			}
62094b51dae9SMat Martineau 		}
62104b51dae9SMat Martineau 
62114b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
62124b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
62134b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
62144b51dae9SMat Martineau 		}
62154b51dae9SMat Martineau 
62164b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
62174b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
62184b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
62194b51dae9SMat Martineau 		}
62204b51dae9SMat Martineau 
62214b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
62224b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
62234b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
62244b51dae9SMat Martineau 		}
62254b51dae9SMat Martineau 	}
62264b51dae9SMat Martineau 
62274b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
62284b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
62294b51dae9SMat Martineau 		    chan->tx_win) {
62304b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62314b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62324b51dae9SMat Martineau 		} else {
62334b51dae9SMat Martineau 			BT_DBG("Expected");
62344b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
62354b51dae9SMat Martineau 		}
62364b51dae9SMat Martineau 	}
62374b51dae9SMat Martineau 
62384b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
62392d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
62404b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
62414b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
62424b51dae9SMat Martineau 	}
62434b51dae9SMat Martineau 
62444b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
62454b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
62464b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
62474b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
62484b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
62494b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
62504b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
62514b51dae9SMat Martineau 		 * request.
62524b51dae9SMat Martineau 		 *
62534b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
62544b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
62554b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
62564b51dae9SMat Martineau 		 *
62574b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
62584b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
62594b51dae9SMat Martineau 		 * causes a disconnect.
62604b51dae9SMat Martineau 		 */
62614b51dae9SMat Martineau 
62624b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
62634b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
62644b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
62654b51dae9SMat Martineau 		} else {
62664b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
62674b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
62684b51dae9SMat Martineau 		}
62694b51dae9SMat Martineau 	} else {
62704b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
62714b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
62724b51dae9SMat Martineau 	}
62734b51dae9SMat Martineau }
62744b51dae9SMat Martineau 
6275d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6276d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6277d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6278d2a7ac5dSMat Martineau {
6279d2a7ac5dSMat Martineau 	int err = 0;
6280941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6281d2a7ac5dSMat Martineau 
6282d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6283d2a7ac5dSMat Martineau 	       event);
6284d2a7ac5dSMat Martineau 
6285d2a7ac5dSMat Martineau 	switch (event) {
6286d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6287d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6288d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6289d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6290d2a7ac5dSMat Martineau 
6291d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6292d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6293d2a7ac5dSMat Martineau 				       control->txseq);
6294d2a7ac5dSMat Martineau 				break;
6295d2a7ac5dSMat Martineau 			}
6296d2a7ac5dSMat Martineau 
6297d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6298d2a7ac5dSMat Martineau 							   control->txseq);
6299d2a7ac5dSMat Martineau 
6300d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6301941247f9SPeter Senna Tschudin 			skb_in_use = true;
6302d2a7ac5dSMat Martineau 
6303d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6304d2a7ac5dSMat Martineau 			if (err)
6305d2a7ac5dSMat Martineau 				break;
6306d2a7ac5dSMat Martineau 
6307d2a7ac5dSMat Martineau 			if (control->final) {
6308d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6309d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6310d2a7ac5dSMat Martineau 					control->final = 0;
6311d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6312d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6313d2a7ac5dSMat Martineau 				}
6314d2a7ac5dSMat Martineau 			}
6315d2a7ac5dSMat Martineau 
6316d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6317d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6318d2a7ac5dSMat Martineau 			break;
6319d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6320d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6321d2a7ac5dSMat Martineau 
6322d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6323d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6324d2a7ac5dSMat Martineau 			 * when local busy is exited.
6325d2a7ac5dSMat Martineau 			 */
6326d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6327d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6328d2a7ac5dSMat Martineau 				       control->txseq);
6329d2a7ac5dSMat Martineau 				break;
6330d2a7ac5dSMat Martineau 			}
6331d2a7ac5dSMat Martineau 
6332d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6333d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6334d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6335d2a7ac5dSMat Martineau 			 */
6336d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6337941247f9SPeter Senna Tschudin 			skb_in_use = true;
6338d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6339d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6340d2a7ac5dSMat Martineau 
6341d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6342d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6343d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6344d2a7ac5dSMat Martineau 
6345d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6346d2a7ac5dSMat Martineau 			break;
6347d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6348d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6349d2a7ac5dSMat Martineau 			break;
6350d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6351d2a7ac5dSMat Martineau 			break;
6352d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6353d2a7ac5dSMat Martineau 		default:
63545e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6355d2a7ac5dSMat Martineau 			break;
6356d2a7ac5dSMat Martineau 		}
6357d2a7ac5dSMat Martineau 		break;
6358d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6359d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6360d2a7ac5dSMat Martineau 		if (control->final) {
6361d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6362d2a7ac5dSMat Martineau 
6363e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6364e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6365d2a7ac5dSMat Martineau 				control->final = 0;
6366d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6367d2a7ac5dSMat Martineau 			}
6368d2a7ac5dSMat Martineau 
6369d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6370d2a7ac5dSMat Martineau 		} else if (control->poll) {
6371d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6372d2a7ac5dSMat Martineau 		} else {
6373d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6374d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6375d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6376d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6377d2a7ac5dSMat Martineau 
6378d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6379d2a7ac5dSMat Martineau 		}
6380d2a7ac5dSMat Martineau 		break;
6381d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6382d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6383d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6384d2a7ac5dSMat Martineau 		if (control && control->poll) {
6385d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6386d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6387d2a7ac5dSMat Martineau 		}
6388d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6389d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6390d2a7ac5dSMat Martineau 		break;
6391d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6392d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6393d2a7ac5dSMat Martineau 		break;
6394d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6395d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6396d2a7ac5dSMat Martineau 		break;
6397d2a7ac5dSMat Martineau 	default:
6398d2a7ac5dSMat Martineau 		break;
6399d2a7ac5dSMat Martineau 	}
6400d2a7ac5dSMat Martineau 
6401d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6402d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6403d2a7ac5dSMat Martineau 		kfree_skb(skb);
6404d2a7ac5dSMat Martineau 	}
6405d2a7ac5dSMat Martineau 
6406d2a7ac5dSMat Martineau 	return err;
6407d2a7ac5dSMat Martineau }
6408d2a7ac5dSMat Martineau 
6409d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6410d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6411d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6412d2a7ac5dSMat Martineau {
6413d2a7ac5dSMat Martineau 	int err = 0;
6414d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6415941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6416d2a7ac5dSMat Martineau 
6417d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6418d2a7ac5dSMat Martineau 	       event);
6419d2a7ac5dSMat Martineau 
6420d2a7ac5dSMat Martineau 	switch (event) {
6421d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6422d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6423d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6424d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6425d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6426d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6427941247f9SPeter Senna Tschudin 			skb_in_use = true;
6428d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6429d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6430d2a7ac5dSMat Martineau 
6431d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
6432d2a7ac5dSMat Martineau 			break;
6433d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
6434d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
6435d2a7ac5dSMat Martineau 
6436d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6437d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6438941247f9SPeter Senna Tschudin 			skb_in_use = true;
6439d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6440d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6441d2a7ac5dSMat Martineau 
6442d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
6443d2a7ac5dSMat Martineau 			if (err)
6444d2a7ac5dSMat Martineau 				break;
6445d2a7ac5dSMat Martineau 
6446d2a7ac5dSMat Martineau 			break;
6447d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6448d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
6449d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
6450d2a7ac5dSMat Martineau 			 * the missing frames.
6451d2a7ac5dSMat Martineau 			 */
6452d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6453941247f9SPeter Senna Tschudin 			skb_in_use = true;
6454d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6455d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6456d2a7ac5dSMat Martineau 
6457d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6458d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6459d2a7ac5dSMat Martineau 			break;
6460d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
6461d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
6462d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
6463d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
6464d2a7ac5dSMat Martineau 			 * SREJ'd frames.
6465d2a7ac5dSMat Martineau 			 */
6466d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6467941247f9SPeter Senna Tschudin 			skb_in_use = true;
6468d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6469d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6470d2a7ac5dSMat Martineau 
6471d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6472d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
6473d2a7ac5dSMat Martineau 			break;
6474d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
6475d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
6476d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6477d2a7ac5dSMat Martineau 			break;
6478d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6479d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
6480d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
6481d2a7ac5dSMat Martineau 			 */
6482d2a7ac5dSMat Martineau 			break;
6483d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6484d2a7ac5dSMat Martineau 			break;
6485d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6486d2a7ac5dSMat Martineau 		default:
64875e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6488d2a7ac5dSMat Martineau 			break;
6489d2a7ac5dSMat Martineau 		}
6490d2a7ac5dSMat Martineau 		break;
6491d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6492d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6493d2a7ac5dSMat Martineau 		if (control->final) {
6494d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6495d2a7ac5dSMat Martineau 
6496d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
6497d2a7ac5dSMat Martineau 						&chan->conn_state)) {
6498d2a7ac5dSMat Martineau 				control->final = 0;
6499d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6500d2a7ac5dSMat Martineau 			}
6501d2a7ac5dSMat Martineau 
6502d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6503d2a7ac5dSMat Martineau 		} else if (control->poll) {
6504d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6505d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6506d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
6507d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6508d2a7ac5dSMat Martineau 			}
6509d2a7ac5dSMat Martineau 
6510d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6511d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6512d2a7ac5dSMat Martineau 		} else {
6513d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6514d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6515d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6516d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6517d2a7ac5dSMat Martineau 
6518d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
6519d2a7ac5dSMat Martineau 		}
6520d2a7ac5dSMat Martineau 		break;
6521d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6522d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6523d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6524d2a7ac5dSMat Martineau 		if (control->poll) {
6525d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
6526d2a7ac5dSMat Martineau 		} else {
6527d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
6528d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
6529d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
6530d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
6531d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
6532d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
6533d2a7ac5dSMat Martineau 		}
6534d2a7ac5dSMat Martineau 
6535d2a7ac5dSMat Martineau 		break;
6536d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6537d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6538d2a7ac5dSMat Martineau 		break;
6539d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6540d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6541d2a7ac5dSMat Martineau 		break;
6542d2a7ac5dSMat Martineau 	}
6543d2a7ac5dSMat Martineau 
6544d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6545d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6546d2a7ac5dSMat Martineau 		kfree_skb(skb);
6547d2a7ac5dSMat Martineau 	}
6548d2a7ac5dSMat Martineau 
6549d2a7ac5dSMat Martineau 	return err;
6550d2a7ac5dSMat Martineau }
6551d2a7ac5dSMat Martineau 
655232b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
655332b32735SMat Martineau {
655432b32735SMat Martineau 	BT_DBG("chan %p", chan);
655532b32735SMat Martineau 
655632b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
655732b32735SMat Martineau 
655832b32735SMat Martineau 	if (chan->hs_hcon)
655932b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
656032b32735SMat Martineau 	else
656132b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
656232b32735SMat Martineau 
656332b32735SMat Martineau 	return l2cap_resegment(chan);
656432b32735SMat Martineau }
656532b32735SMat Martineau 
656632b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
656732b32735SMat Martineau 				 struct l2cap_ctrl *control,
656832b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
656932b32735SMat Martineau {
657032b32735SMat Martineau 	int err;
657132b32735SMat Martineau 
657232b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
657332b32735SMat Martineau 	       event);
657432b32735SMat Martineau 
657532b32735SMat Martineau 	if (!control->poll)
657632b32735SMat Martineau 		return -EPROTO;
657732b32735SMat Martineau 
657832b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
657932b32735SMat Martineau 
658032b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
658132b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
658232b32735SMat Martineau 	else
658332b32735SMat Martineau 		chan->tx_send_head = NULL;
658432b32735SMat Martineau 
658532b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
658632b32735SMat Martineau 	 * by the receiver.
658732b32735SMat Martineau 	 */
658832b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
658932b32735SMat Martineau 	chan->unacked_frames = 0;
659032b32735SMat Martineau 
659132b32735SMat Martineau 	err = l2cap_finish_move(chan);
659232b32735SMat Martineau 	if (err)
659332b32735SMat Martineau 		return err;
659432b32735SMat Martineau 
659532b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
659632b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
659732b32735SMat Martineau 
659832b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
659932b32735SMat Martineau 		return -EPROTO;
660032b32735SMat Martineau 
660132b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
660232b32735SMat Martineau }
660332b32735SMat Martineau 
660432b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
660532b32735SMat Martineau 				 struct l2cap_ctrl *control,
660632b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
660732b32735SMat Martineau {
660832b32735SMat Martineau 	int err;
660932b32735SMat Martineau 
661032b32735SMat Martineau 	if (!control->final)
661132b32735SMat Martineau 		return -EPROTO;
661232b32735SMat Martineau 
661332b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
661432b32735SMat Martineau 
661532b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
661632b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
661732b32735SMat Martineau 
661832b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
661932b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
662032b32735SMat Martineau 	else
662132b32735SMat Martineau 		chan->tx_send_head = NULL;
662232b32735SMat Martineau 
662332b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
662432b32735SMat Martineau 	 * by the receiver.
662532b32735SMat Martineau 	 */
662632b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
662732b32735SMat Martineau 	chan->unacked_frames = 0;
662832b32735SMat Martineau 
662932b32735SMat Martineau 	if (chan->hs_hcon)
663032b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
663132b32735SMat Martineau 	else
663232b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
663332b32735SMat Martineau 
663432b32735SMat Martineau 	err = l2cap_resegment(chan);
663532b32735SMat Martineau 
663632b32735SMat Martineau 	if (!err)
663732b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
663832b32735SMat Martineau 
663932b32735SMat Martineau 	return err;
664032b32735SMat Martineau }
664132b32735SMat Martineau 
6642d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
6643d2a7ac5dSMat Martineau {
6644d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
6645d2a7ac5dSMat Martineau 	u16 unacked;
6646d2a7ac5dSMat Martineau 
6647d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
6648d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
6649d2a7ac5dSMat Martineau }
6650d2a7ac5dSMat Martineau 
6651cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6652cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
66530a708f8fSGustavo F. Padovan {
6654d2a7ac5dSMat Martineau 	int err = 0;
6655d2a7ac5dSMat Martineau 
6656d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
6657d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
6658d2a7ac5dSMat Martineau 
6659d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
6660d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
6661d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
6662d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
6663d2a7ac5dSMat Martineau 			break;
6664d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
6665d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
6666d2a7ac5dSMat Martineau 						       event);
6667d2a7ac5dSMat Martineau 			break;
666832b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
666932b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
667032b32735SMat Martineau 			break;
667132b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
667232b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
667332b32735SMat Martineau 			break;
6674d2a7ac5dSMat Martineau 		default:
6675d2a7ac5dSMat Martineau 			/* shut it down */
6676d2a7ac5dSMat Martineau 			break;
6677d2a7ac5dSMat Martineau 		}
6678d2a7ac5dSMat Martineau 	} else {
6679d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
6680d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
6681d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
66825e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6683d2a7ac5dSMat Martineau 	}
6684d2a7ac5dSMat Martineau 
6685d2a7ac5dSMat Martineau 	return err;
6686cec8ab6eSMat Martineau }
6687cec8ab6eSMat Martineau 
6688cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
6689cec8ab6eSMat Martineau 			   struct sk_buff *skb)
6690cec8ab6eSMat Martineau {
66914b51dae9SMat Martineau 	int err = 0;
66924b51dae9SMat Martineau 
66934b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
66944b51dae9SMat Martineau 	       chan->rx_state);
66954b51dae9SMat Martineau 
66964b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
66974b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
66984b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
66994b51dae9SMat Martineau 
67004b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
67014b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
67024b51dae9SMat Martineau 
67034b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
67044b51dae9SMat Martineau 
67054b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
67064b51dae9SMat Martineau 	} else {
67074b51dae9SMat Martineau 		if (chan->sdu) {
67084b51dae9SMat Martineau 			kfree_skb(chan->sdu);
67094b51dae9SMat Martineau 			chan->sdu = NULL;
67104b51dae9SMat Martineau 		}
67114b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
67124b51dae9SMat Martineau 		chan->sdu_len = 0;
67134b51dae9SMat Martineau 
67144b51dae9SMat Martineau 		if (skb) {
67154b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
67164b51dae9SMat Martineau 			kfree_skb(skb);
67174b51dae9SMat Martineau 		}
67184b51dae9SMat Martineau 	}
67194b51dae9SMat Martineau 
67204b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
67214b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
67224b51dae9SMat Martineau 
67234b51dae9SMat Martineau 	return err;
6724cec8ab6eSMat Martineau }
6725cec8ab6eSMat Martineau 
6726cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6727cec8ab6eSMat Martineau {
6728cec8ab6eSMat Martineau 	struct l2cap_ctrl *control = &bt_cb(skb)->control;
6729cec8ab6eSMat Martineau 	u16 len;
6730cec8ab6eSMat Martineau 	u8 event;
67310a708f8fSGustavo F. Padovan 
6732b76bbd66SMat Martineau 	__unpack_control(chan, skb);
6733b76bbd66SMat Martineau 
67340a708f8fSGustavo F. Padovan 	len = skb->len;
67350a708f8fSGustavo F. Padovan 
67360a708f8fSGustavo F. Padovan 	/*
67370a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
67380a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
6739cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
67400a708f8fSGustavo F. Padovan 	 */
674147d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
67420a708f8fSGustavo F. Padovan 		goto drop;
67430a708f8fSGustavo F. Padovan 
6744cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
674503a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
67460a708f8fSGustavo F. Padovan 
674747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
674803a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
67490a708f8fSGustavo F. Padovan 
675047d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
67515e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
67520a708f8fSGustavo F. Padovan 		goto drop;
67530a708f8fSGustavo F. Padovan 	}
67540a708f8fSGustavo F. Padovan 
6755cec8ab6eSMat Martineau 	if (!control->sframe) {
6756cec8ab6eSMat Martineau 		int err;
67570a708f8fSGustavo F. Padovan 
6758cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
6759cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
6760cec8ab6eSMat Martineau 		       control->txseq);
6761836be934SAndrei Emeltchenko 
6762cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
6763cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
6764cec8ab6eSMat Martineau 		 */
6765cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
67660a708f8fSGustavo F. Padovan 			goto drop;
67670a708f8fSGustavo F. Padovan 
6768cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
6769cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
6770cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
67710a708f8fSGustavo F. Padovan 		} else {
6772cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
6773cec8ab6eSMat Martineau 		}
6774cec8ab6eSMat Martineau 
6775cec8ab6eSMat Martineau 		if (err)
67765e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6777cec8ab6eSMat Martineau 	} else {
6778cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
6779cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
6780cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
6781cec8ab6eSMat Martineau 		};
6782cec8ab6eSMat Martineau 
6783cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
6784cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
6785cec8ab6eSMat Martineau 			goto drop;
6786cec8ab6eSMat Martineau 
6787cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
6788cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
6789cec8ab6eSMat Martineau 		       control->super);
6790cec8ab6eSMat Martineau 
67910a708f8fSGustavo F. Padovan 		if (len != 0) {
67921bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
67935e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
67940a708f8fSGustavo F. Padovan 			goto drop;
67950a708f8fSGustavo F. Padovan 		}
67960a708f8fSGustavo F. Padovan 
6797cec8ab6eSMat Martineau 		/* Validate F and P bits */
6798cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
6799cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
6800cec8ab6eSMat Martineau 			goto drop;
6801cec8ab6eSMat Martineau 
6802cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
6803cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
68045e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
68050a708f8fSGustavo F. Padovan 	}
68060a708f8fSGustavo F. Padovan 
68070a708f8fSGustavo F. Padovan 	return 0;
68080a708f8fSGustavo F. Padovan 
68090a708f8fSGustavo F. Padovan drop:
68100a708f8fSGustavo F. Padovan 	kfree_skb(skb);
68110a708f8fSGustavo F. Padovan 	return 0;
68120a708f8fSGustavo F. Padovan }
68130a708f8fSGustavo F. Padovan 
6814b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
6815b1c325c2SJohan Hedberg {
6816b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
6817b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
6818b1c325c2SJohan Hedberg 	u16 return_credits;
6819b1c325c2SJohan Hedberg 
6820b1c325c2SJohan Hedberg 	/* We return more credits to the sender only after the amount of
6821b1c325c2SJohan Hedberg 	 * credits falls below half of the initial amount.
6822b1c325c2SJohan Hedberg 	 */
6823b1c325c2SJohan Hedberg 	if (chan->rx_credits >= (L2CAP_LE_MAX_CREDITS + 1) / 2)
6824b1c325c2SJohan Hedberg 		return;
6825b1c325c2SJohan Hedberg 
6826b1c325c2SJohan Hedberg 	return_credits = L2CAP_LE_MAX_CREDITS - chan->rx_credits;
6827b1c325c2SJohan Hedberg 
6828b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
6829b1c325c2SJohan Hedberg 
6830b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
6831b1c325c2SJohan Hedberg 
6832b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
6833b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
6834b1c325c2SJohan Hedberg 
6835b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
6836b1c325c2SJohan Hedberg 
6837b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
6838b1c325c2SJohan Hedberg }
6839b1c325c2SJohan Hedberg 
6840fad5fc89SJohan Hedberg static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
6841fad5fc89SJohan Hedberg {
6842aac23bf6SJohan Hedberg 	int err;
6843fad5fc89SJohan Hedberg 
6844aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
6845aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
6846fad5fc89SJohan Hedberg 		return -ENOBUFS;
6847aac23bf6SJohan Hedberg 	}
6848aac23bf6SJohan Hedberg 
6849aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
6850aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
6851aac23bf6SJohan Hedberg 		return -ENOBUFS;
6852aac23bf6SJohan Hedberg 	}
6853fad5fc89SJohan Hedberg 
6854fad5fc89SJohan Hedberg 	chan->rx_credits--;
6855fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
6856fad5fc89SJohan Hedberg 
6857fad5fc89SJohan Hedberg 	l2cap_chan_le_send_credits(chan);
6858fad5fc89SJohan Hedberg 
6859aac23bf6SJohan Hedberg 	err = 0;
6860aac23bf6SJohan Hedberg 
6861aac23bf6SJohan Hedberg 	if (!chan->sdu) {
6862aac23bf6SJohan Hedberg 		u16 sdu_len;
6863aac23bf6SJohan Hedberg 
6864aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
6865aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
6866aac23bf6SJohan Hedberg 
6867aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
6868aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
6869aac23bf6SJohan Hedberg 
6870aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
6871aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
6872aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
6873aac23bf6SJohan Hedberg 			goto failed;
6874aac23bf6SJohan Hedberg 		}
6875aac23bf6SJohan Hedberg 
6876aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
6877aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
6878aac23bf6SJohan Hedberg 			err = -EINVAL;
6879aac23bf6SJohan Hedberg 			goto failed;
6880aac23bf6SJohan Hedberg 		}
6881aac23bf6SJohan Hedberg 
6882aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
6883fad5fc89SJohan Hedberg 			return chan->ops->recv(chan, skb);
6884aac23bf6SJohan Hedberg 
6885aac23bf6SJohan Hedberg 		chan->sdu = skb;
6886aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
6887aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
6888aac23bf6SJohan Hedberg 
6889aac23bf6SJohan Hedberg 		return 0;
6890aac23bf6SJohan Hedberg 	}
6891aac23bf6SJohan Hedberg 
6892aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
6893aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
6894aac23bf6SJohan Hedberg 
6895aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
6896aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
6897aac23bf6SJohan Hedberg 		err = -EINVAL;
6898aac23bf6SJohan Hedberg 		goto failed;
6899aac23bf6SJohan Hedberg 	}
6900aac23bf6SJohan Hedberg 
6901aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
6902aac23bf6SJohan Hedberg 	skb = NULL;
6903aac23bf6SJohan Hedberg 
6904aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
6905aac23bf6SJohan Hedberg 		err = chan->ops->recv(chan, chan->sdu);
6906aac23bf6SJohan Hedberg 		if (!err) {
6907aac23bf6SJohan Hedberg 			chan->sdu = NULL;
6908aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
6909aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
6910aac23bf6SJohan Hedberg 		}
6911aac23bf6SJohan Hedberg 	}
6912aac23bf6SJohan Hedberg 
6913aac23bf6SJohan Hedberg failed:
6914aac23bf6SJohan Hedberg 	if (err) {
6915aac23bf6SJohan Hedberg 		kfree_skb(skb);
6916aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
6917aac23bf6SJohan Hedberg 		chan->sdu = NULL;
6918aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
6919aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
6920aac23bf6SJohan Hedberg 	}
6921aac23bf6SJohan Hedberg 
6922aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
6923aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
6924aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
6925aac23bf6SJohan Hedberg 	 */
6926aac23bf6SJohan Hedberg 	return 0;
6927fad5fc89SJohan Hedberg }
6928fad5fc89SJohan Hedberg 
692913ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
693013ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
69310a708f8fSGustavo F. Padovan {
693248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
69330a708f8fSGustavo F. Padovan 
6934baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
693548454079SGustavo F. Padovan 	if (!chan) {
693697e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
693797e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
693897e8e89dSAndrei Emeltchenko 			if (!chan) {
693997e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
694013ca56e0SAndrei Emeltchenko 				return;
694197e8e89dSAndrei Emeltchenko 			}
694297e8e89dSAndrei Emeltchenko 
694397e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
694497e8e89dSAndrei Emeltchenko 		} else {
69450a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
69466be36555SAndrei Emeltchenko 			/* Drop packet and return */
69473379013bSDan Carpenter 			kfree_skb(skb);
694813ca56e0SAndrei Emeltchenko 			return;
69490a708f8fSGustavo F. Padovan 		}
695097e8e89dSAndrei Emeltchenko 	}
69510a708f8fSGustavo F. Padovan 
695249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
69530a708f8fSGustavo F. Padovan 
695489bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
69550a708f8fSGustavo F. Padovan 		goto drop;
69560a708f8fSGustavo F. Padovan 
69570c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
695838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
6959fad5fc89SJohan Hedberg 		if (l2cap_le_data_rcv(chan, skb) < 0)
6960fad5fc89SJohan Hedberg 			goto drop;
6961fad5fc89SJohan Hedberg 
6962fad5fc89SJohan Hedberg 		goto done;
6963fad5fc89SJohan Hedberg 
69640a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
69650a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
69660a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
69670a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
69680a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
69690a708f8fSGustavo F. Padovan 
69700c1bc5c6SGustavo F. Padovan 		if (chan->imtu < skb->len)
69710a708f8fSGustavo F. Padovan 			goto drop;
69720a708f8fSGustavo F. Padovan 
697380b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
69740a708f8fSGustavo F. Padovan 			goto done;
69750a708f8fSGustavo F. Padovan 		break;
69760a708f8fSGustavo F. Padovan 
69770a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
69780a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
6979cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
69800a708f8fSGustavo F. Padovan 		goto done;
69810a708f8fSGustavo F. Padovan 
69820a708f8fSGustavo F. Padovan 	default:
69830c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
69840a708f8fSGustavo F. Padovan 		break;
69850a708f8fSGustavo F. Padovan 	}
69860a708f8fSGustavo F. Padovan 
69870a708f8fSGustavo F. Padovan drop:
69880a708f8fSGustavo F. Padovan 	kfree_skb(skb);
69890a708f8fSGustavo F. Padovan 
69900a708f8fSGustavo F. Padovan done:
69916be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
69920a708f8fSGustavo F. Padovan }
69930a708f8fSGustavo F. Padovan 
699484104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
699584104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
69960a708f8fSGustavo F. Padovan {
6997ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
699823691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
69990a708f8fSGustavo F. Padovan 
7000ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
7001ae4fd2d3SMarcel Holtmann 		goto drop;
7002ae4fd2d3SMarcel Holtmann 
7003bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
7004bf20fd4eSJohan Hedberg 					ACL_LINK);
700523691d75SGustavo F. Padovan 	if (!chan)
70060a708f8fSGustavo F. Padovan 		goto drop;
70070a708f8fSGustavo F. Padovan 
70085b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
70090a708f8fSGustavo F. Padovan 
701089bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
70110a708f8fSGustavo F. Padovan 		goto drop;
70120a708f8fSGustavo F. Padovan 
7013e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
70140a708f8fSGustavo F. Padovan 		goto drop;
70150a708f8fSGustavo F. Padovan 
70162edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
701706ae3314SMarcel Holtmann 	bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
70182edf870dSMarcel Holtmann 	bt_cb(skb)->psm = psm;
70192edf870dSMarcel Holtmann 
702080b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
702184104b24SAndrei Emeltchenko 		return;
70220a708f8fSGustavo F. Padovan 
70230a708f8fSGustavo F. Padovan drop:
70240a708f8fSGustavo F. Padovan 	kfree_skb(skb);
70250a708f8fSGustavo F. Padovan }
70260a708f8fSGustavo F. Padovan 
702772f78356SMarcel Holtmann static void l2cap_att_channel(struct l2cap_conn *conn,
7028d9b88702SAndrei Emeltchenko 			      struct sk_buff *skb)
70299f69bda6SGustavo F. Padovan {
7030b99707d7SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
703123691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
70329f69bda6SGustavo F. Padovan 
7033b99707d7SMarcel Holtmann 	if (hcon->type != LE_LINK)
7034b99707d7SMarcel Holtmann 		goto drop;
7035b99707d7SMarcel Holtmann 
7036af1c0134SJohan Hedberg 	chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
703706ae3314SMarcel Holtmann 					 &hcon->src, &hcon->dst);
703823691d75SGustavo F. Padovan 	if (!chan)
70399f69bda6SGustavo F. Padovan 		goto drop;
70409f69bda6SGustavo F. Padovan 
70415b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
70429f69bda6SGustavo F. Padovan 
7043cc8dba2bSMarcel Holtmann 	if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
7044cc8dba2bSMarcel Holtmann 		goto drop;
7045cc8dba2bSMarcel Holtmann 
7046e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
70479f69bda6SGustavo F. Padovan 		goto drop;
70489f69bda6SGustavo F. Padovan 
704980b98027SGustavo Padovan 	if (!chan->ops->recv(chan, skb))
70506810fca7SAndrei Emeltchenko 		return;
70519f69bda6SGustavo F. Padovan 
70529f69bda6SGustavo F. Padovan drop:
70539f69bda6SGustavo F. Padovan 	kfree_skb(skb);
70549f69bda6SGustavo F. Padovan }
70559f69bda6SGustavo F. Padovan 
70560a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
70570a708f8fSGustavo F. Padovan {
70580a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
70590a708f8fSGustavo F. Padovan 	u16 cid, len;
70600a708f8fSGustavo F. Padovan 	__le16 psm;
70610a708f8fSGustavo F. Padovan 
70620a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
70630a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
70640a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
70650a708f8fSGustavo F. Padovan 
70660a708f8fSGustavo F. Padovan 	if (len != skb->len) {
70670a708f8fSGustavo F. Padovan 		kfree_skb(skb);
70680a708f8fSGustavo F. Padovan 		return;
70690a708f8fSGustavo F. Padovan 	}
70700a708f8fSGustavo F. Padovan 
70710a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
70720a708f8fSGustavo F. Padovan 
70730a708f8fSGustavo F. Padovan 	switch (cid) {
70740a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
70750a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
70760a708f8fSGustavo F. Padovan 		break;
70770a708f8fSGustavo F. Padovan 
70780a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7079097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
70800181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
70810a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
70820a708f8fSGustavo F. Padovan 		break;
70830a708f8fSGustavo F. Padovan 
7084073d1cf3SJohan Hedberg 	case L2CAP_CID_ATT:
708572f78356SMarcel Holtmann 		l2cap_att_channel(conn, skb);
70869f69bda6SGustavo F. Padovan 		break;
70879f69bda6SGustavo F. Padovan 
7088a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7089a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7090a2877629SMarcel Holtmann 		break;
7091a2877629SMarcel Holtmann 
7092b501d6a1SAnderson Briglia 	case L2CAP_CID_SMP:
7093b501d6a1SAnderson Briglia 		if (smp_sig_channel(conn, skb))
7094b501d6a1SAnderson Briglia 			l2cap_conn_del(conn->hcon, EACCES);
7095b501d6a1SAnderson Briglia 		break;
7096b501d6a1SAnderson Briglia 
70970a708f8fSGustavo F. Padovan 	default:
70980a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
70990a708f8fSGustavo F. Padovan 		break;
71000a708f8fSGustavo F. Padovan 	}
71010a708f8fSGustavo F. Padovan }
71020a708f8fSGustavo F. Padovan 
71030a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
71040a708f8fSGustavo F. Padovan 
7105686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
71060a708f8fSGustavo F. Padovan {
71070a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
710823691d75SGustavo F. Padovan 	struct l2cap_chan *c;
71090a708f8fSGustavo F. Padovan 
71106ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
71110a708f8fSGustavo F. Padovan 
71120a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
711323691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
711423691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
711589bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
71160a708f8fSGustavo F. Padovan 			continue;
71170a708f8fSGustavo F. Padovan 
71187eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
71190a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
712043bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71210a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
71220a708f8fSGustavo F. Padovan 			exact++;
71237eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
71240a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
712543bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
71260a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
71270a708f8fSGustavo F. Padovan 		}
71280a708f8fSGustavo F. Padovan 	}
712923691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
71300a708f8fSGustavo F. Padovan 
71310a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
71320a708f8fSGustavo F. Padovan }
71330a708f8fSGustavo F. Padovan 
71349e664631SAndrei Emeltchenko void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
71350a708f8fSGustavo F. Padovan {
71360a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
71370a708f8fSGustavo F. Padovan 
71386ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
71390a708f8fSGustavo F. Padovan 
71400a708f8fSGustavo F. Padovan 	if (!status) {
7141baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
71420a708f8fSGustavo F. Padovan 		if (conn)
71430a708f8fSGustavo F. Padovan 			l2cap_conn_ready(conn);
7144ba6fc317SAndrei Emeltchenko 	} else {
7145e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
7146ba6fc317SAndrei Emeltchenko 	}
71470a708f8fSGustavo F. Padovan }
71480a708f8fSGustavo F. Padovan 
7149686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
71500a708f8fSGustavo F. Padovan {
71510a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
71520a708f8fSGustavo F. Padovan 
71530a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
71540a708f8fSGustavo F. Padovan 
7155686ebf28SUlisses Furquim 	if (!conn)
71569f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
71570a708f8fSGustavo F. Padovan 	return conn->disc_reason;
71580a708f8fSGustavo F. Padovan }
71590a708f8fSGustavo F. Padovan 
71609e664631SAndrei Emeltchenko void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
71610a708f8fSGustavo F. Padovan {
71620a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
71630a708f8fSGustavo F. Padovan 
7164e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
71650a708f8fSGustavo F. Padovan }
71660a708f8fSGustavo F. Padovan 
71674343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
71680a708f8fSGustavo F. Padovan {
7169715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
71700a708f8fSGustavo F. Padovan 		return;
71710a708f8fSGustavo F. Padovan 
71720a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
71734343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
7174ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
71754343478fSGustavo F. Padovan 		} else if (chan->sec_level == BT_SECURITY_HIGH)
71760f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
71770a708f8fSGustavo F. Padovan 	} else {
71784343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
7179c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
71800a708f8fSGustavo F. Padovan 	}
71810a708f8fSGustavo F. Padovan }
71820a708f8fSGustavo F. Padovan 
7183686ebf28SUlisses Furquim int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
71840a708f8fSGustavo F. Padovan {
71850a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
718648454079SGustavo F. Padovan 	struct l2cap_chan *chan;
71870a708f8fSGustavo F. Padovan 
71880a708f8fSGustavo F. Padovan 	if (!conn)
71890a708f8fSGustavo F. Padovan 		return 0;
71900a708f8fSGustavo F. Padovan 
719189d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
71920a708f8fSGustavo F. Padovan 
7193160dc6acSVinicius Costa Gomes 	if (hcon->type == LE_LINK) {
719435d4adccSHemant Gupta 		if (!status && encrypt)
7195160dc6acSVinicius Costa Gomes 			smp_distribute_keys(conn, 0);
719617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->security_timer);
7197160dc6acSVinicius Costa Gomes 	}
7198160dc6acSVinicius Costa Gomes 
71993df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
72000a708f8fSGustavo F. Padovan 
72013df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
72026be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
72030a708f8fSGustavo F. Padovan 
720489d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
720589d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
7206f1cb9af5SVinicius Costa Gomes 
720778eb2f98SAndrei Emeltchenko 		if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
720878eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
720978eb2f98SAndrei Emeltchenko 			continue;
721078eb2f98SAndrei Emeltchenko 		}
721178eb2f98SAndrei Emeltchenko 
7212073d1cf3SJohan Hedberg 		if (chan->scid == L2CAP_CID_ATT) {
7213f1cb9af5SVinicius Costa Gomes 			if (!status && encrypt) {
7214f1cb9af5SVinicius Costa Gomes 				chan->sec_level = hcon->sec_level;
7215cf4cd009SAndrei Emeltchenko 				l2cap_chan_ready(chan);
7216f1cb9af5SVinicius Costa Gomes 			}
7217f1cb9af5SVinicius Costa Gomes 
72186be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
7219f1cb9af5SVinicius Costa Gomes 			continue;
7220f1cb9af5SVinicius Costa Gomes 		}
7221f1cb9af5SVinicius Costa Gomes 
722296eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
72236be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72240a708f8fSGustavo F. Padovan 			continue;
72250a708f8fSGustavo F. Padovan 		}
72260a708f8fSGustavo F. Padovan 
722789bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
722889bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
7229d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
72304343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
72316be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
72320a708f8fSGustavo F. Padovan 			continue;
72330a708f8fSGustavo F. Padovan 		}
72340a708f8fSGustavo F. Padovan 
723589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
72366d3c15daSJohan Hedberg 			if (!status)
723793c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
72386d3c15daSJohan Hedberg 			else
7239ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
724089bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
72410a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
7242df3c3931SJohan Hedberg 			__u16 res, stat;
72430a708f8fSGustavo F. Padovan 
72440a708f8fSGustavo F. Padovan 			if (!status) {
7245bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
7246df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
7247df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
72482dc4e510SGustavo Padovan 					chan->ops->defer(chan);
7249df3c3931SJohan Hedberg 				} else {
7250acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
7251df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
7252df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
7253df3c3931SJohan Hedberg 				}
72540a708f8fSGustavo F. Padovan 			} else {
7255acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
7256ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
7257df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
7258df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
72590a708f8fSGustavo F. Padovan 			}
72600a708f8fSGustavo F. Padovan 
7261fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
7262fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
7263df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
7264df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
7265fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
7266fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
72672d369359SMat Martineau 
72682d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
72692d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
72702d369359SMat Martineau 				char buf[128];
72712d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
72722d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
72732d369359SMat Martineau 					       L2CAP_CONF_REQ,
72742d369359SMat Martineau 					       l2cap_build_conf_req(chan, buf),
72752d369359SMat Martineau 					       buf);
72762d369359SMat Martineau 				chan->num_conf_req++;
72772d369359SMat Martineau 			}
72780a708f8fSGustavo F. Padovan 		}
72790a708f8fSGustavo F. Padovan 
72806be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
72810a708f8fSGustavo F. Padovan 	}
72820a708f8fSGustavo F. Padovan 
72833df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
72840a708f8fSGustavo F. Padovan 
72850a708f8fSGustavo F. Padovan 	return 0;
72860a708f8fSGustavo F. Padovan }
72870a708f8fSGustavo F. Padovan 
7288686ebf28SUlisses Furquim int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
72890a708f8fSGustavo F. Padovan {
72900a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
7291d73a0988SAndrei Emeltchenko 	struct l2cap_hdr *hdr;
7292d73a0988SAndrei Emeltchenko 	int len;
72930a708f8fSGustavo F. Padovan 
72941d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
72951d13a254SAndrei Emeltchenko 	if (!conn && hcon->hdev->dev_type != HCI_BREDR)
72961d13a254SAndrei Emeltchenko 		goto drop;
72970a708f8fSGustavo F. Padovan 
72980a708f8fSGustavo F. Padovan 	if (!conn)
7299baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
73000a708f8fSGustavo F. Padovan 
73010a708f8fSGustavo F. Padovan 	if (!conn)
73020a708f8fSGustavo F. Padovan 		goto drop;
73030a708f8fSGustavo F. Padovan 
73040a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
73050a708f8fSGustavo F. Padovan 
7306d73a0988SAndrei Emeltchenko 	switch (flags) {
7307d73a0988SAndrei Emeltchenko 	case ACL_START:
7308d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
7309d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
73100a708f8fSGustavo F. Padovan 		if (conn->rx_len) {
73110a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
73120a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
73130a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
73140a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
73150a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73160a708f8fSGustavo F. Padovan 		}
73170a708f8fSGustavo F. Padovan 
73180a708f8fSGustavo F. Padovan 		/* Start fragment always begin with Basic L2CAP header */
73190a708f8fSGustavo F. Padovan 		if (skb->len < L2CAP_HDR_SIZE) {
73200a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too short (len %d)", skb->len);
73210a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73220a708f8fSGustavo F. Padovan 			goto drop;
73230a708f8fSGustavo F. Padovan 		}
73240a708f8fSGustavo F. Padovan 
73250a708f8fSGustavo F. Padovan 		hdr = (struct l2cap_hdr *) skb->data;
73260a708f8fSGustavo F. Padovan 		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
73270a708f8fSGustavo F. Padovan 
73280a708f8fSGustavo F. Padovan 		if (len == skb->len) {
73290a708f8fSGustavo F. Padovan 			/* Complete frame received */
73300a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
73310a708f8fSGustavo F. Padovan 			return 0;
73320a708f8fSGustavo F. Padovan 		}
73330a708f8fSGustavo F. Padovan 
73340a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
73350a708f8fSGustavo F. Padovan 
73360a708f8fSGustavo F. Padovan 		if (skb->len > len) {
73370a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
73380a708f8fSGustavo F. Padovan 			       skb->len, len);
73390a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73400a708f8fSGustavo F. Padovan 			goto drop;
73410a708f8fSGustavo F. Padovan 		}
73420a708f8fSGustavo F. Padovan 
73430a708f8fSGustavo F. Padovan 		/* Allocate skb for the complete frame (with header) */
73448bcde1f2SGustavo Padovan 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
73450a708f8fSGustavo F. Padovan 		if (!conn->rx_skb)
73460a708f8fSGustavo F. Padovan 			goto drop;
73470a708f8fSGustavo F. Padovan 
73480a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73490a708f8fSGustavo F. Padovan 					  skb->len);
73500a708f8fSGustavo F. Padovan 		conn->rx_len = len - skb->len;
7351d73a0988SAndrei Emeltchenko 		break;
7352d73a0988SAndrei Emeltchenko 
7353d73a0988SAndrei Emeltchenko 	case ACL_CONT:
73540a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
73550a708f8fSGustavo F. Padovan 
73560a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
73570a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
73580a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73590a708f8fSGustavo F. Padovan 			goto drop;
73600a708f8fSGustavo F. Padovan 		}
73610a708f8fSGustavo F. Padovan 
73620a708f8fSGustavo F. Padovan 		if (skb->len > conn->rx_len) {
73630a708f8fSGustavo F. Padovan 			BT_ERR("Fragment is too long (len %d, expected %d)",
73640a708f8fSGustavo F. Padovan 			       skb->len, conn->rx_len);
73650a708f8fSGustavo F. Padovan 			kfree_skb(conn->rx_skb);
73660a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
73670a708f8fSGustavo F. Padovan 			conn->rx_len = 0;
73680a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
73690a708f8fSGustavo F. Padovan 			goto drop;
73700a708f8fSGustavo F. Padovan 		}
73710a708f8fSGustavo F. Padovan 
73720a708f8fSGustavo F. Padovan 		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
73730a708f8fSGustavo F. Padovan 					  skb->len);
73740a708f8fSGustavo F. Padovan 		conn->rx_len -= skb->len;
73750a708f8fSGustavo F. Padovan 
73760a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
7377c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
7378c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
7379c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
7380c4e5bafaSJohan Hedberg 			 */
7381c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
73820a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
7383c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
73840a708f8fSGustavo F. Padovan 		}
7385d73a0988SAndrei Emeltchenko 		break;
73860a708f8fSGustavo F. Padovan 	}
73870a708f8fSGustavo F. Padovan 
73880a708f8fSGustavo F. Padovan drop:
73890a708f8fSGustavo F. Padovan 	kfree_skb(skb);
73900a708f8fSGustavo F. Padovan 	return 0;
73910a708f8fSGustavo F. Padovan }
73920a708f8fSGustavo F. Padovan 
73930a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
73940a708f8fSGustavo F. Padovan {
739523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
73960a708f8fSGustavo F. Padovan 
7397333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
73980a708f8fSGustavo F. Padovan 
739923691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
7400fcb73338SAndrei Emeltchenko 		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
74017eafc59eSMarcel Holtmann 			   &c->src, &c->dst,
740289bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
740323691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
740423691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
74050a708f8fSGustavo F. Padovan 	}
74060a708f8fSGustavo F. Padovan 
7407333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
74080a708f8fSGustavo F. Padovan 
74090a708f8fSGustavo F. Padovan 	return 0;
74100a708f8fSGustavo F. Padovan }
74110a708f8fSGustavo F. Padovan 
74120a708f8fSGustavo F. Padovan static int l2cap_debugfs_open(struct inode *inode, struct file *file)
74130a708f8fSGustavo F. Padovan {
74140a708f8fSGustavo F. Padovan 	return single_open(file, l2cap_debugfs_show, inode->i_private);
74150a708f8fSGustavo F. Padovan }
74160a708f8fSGustavo F. Padovan 
74170a708f8fSGustavo F. Padovan static const struct file_operations l2cap_debugfs_fops = {
74180a708f8fSGustavo F. Padovan 	.open		= l2cap_debugfs_open,
74190a708f8fSGustavo F. Padovan 	.read		= seq_read,
74200a708f8fSGustavo F. Padovan 	.llseek		= seq_lseek,
74210a708f8fSGustavo F. Padovan 	.release	= single_release,
74220a708f8fSGustavo F. Padovan };
74230a708f8fSGustavo F. Padovan 
74240a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
74250a708f8fSGustavo F. Padovan 
742664274518SGustavo F. Padovan int __init l2cap_init(void)
74270a708f8fSGustavo F. Padovan {
74280a708f8fSGustavo F. Padovan 	int err;
74290a708f8fSGustavo F. Padovan 
7430bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
74310a708f8fSGustavo F. Padovan 	if (err < 0)
74320a708f8fSGustavo F. Padovan 		return err;
74330a708f8fSGustavo F. Padovan 
74341120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
74351120e4bfSMarcel Holtmann 		return 0;
74361120e4bfSMarcel Holtmann 
74372d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
74382d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
74390a708f8fSGustavo F. Padovan 
74400a708f8fSGustavo F. Padovan 	return 0;
74410a708f8fSGustavo F. Padovan }
74420a708f8fSGustavo F. Padovan 
744364274518SGustavo F. Padovan void l2cap_exit(void)
74440a708f8fSGustavo F. Padovan {
74450a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
7446bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
74470a708f8fSGustavo F. Padovan }
74480a708f8fSGustavo F. Padovan 
74490a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
74500a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
7451