xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision be859723)
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>
35dbb50887SDaniel Borkmann #include <linux/filter.h>
360a708f8fSGustavo F. Padovan 
370a708f8fSGustavo F. Padovan #include <net/bluetooth/bluetooth.h>
380a708f8fSGustavo F. Padovan #include <net/bluetooth/hci_core.h>
390a708f8fSGustavo F. Padovan #include <net/bluetooth/l2cap.h>
407ef9fbf0SMarcel Holtmann 
41ac4b7236SMarcel Holtmann #include "smp.h"
427024728eSMarcel Holtmann #include "a2mp.h"
437ef9fbf0SMarcel Holtmann #include "amp.h"
440a708f8fSGustavo F. Padovan 
450f1bfe4eSJohan Hedberg #define LE_FLOWCTL_MAX_CREDITS 65535
460f1bfe4eSJohan Hedberg 
47d1de6d46SMat Martineau bool disable_ertm;
484be5ca67SLuiz Augusto von Dentz bool enable_ecred;
490a708f8fSGustavo F. Padovan 
50547d1032SMarcel Holtmann static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
510a708f8fSGustavo F. Padovan 
52b5ad8b7fSJohannes Berg static LIST_HEAD(chan_list);
53b5ad8b7fSJohannes Berg static DEFINE_RWLOCK(chan_list_lock);
540a708f8fSGustavo F. Padovan 
550a708f8fSGustavo F. Padovan static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
560a708f8fSGustavo F. Padovan 				       u8 code, u8 ident, u16 dlen, void *data);
574519de9aSGustavo F. Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
584519de9aSGustavo F. Padovan 			   void *data);
59e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
605e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
610a708f8fSGustavo F. Padovan 
62d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
63608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event);
64608bcc6dSMat Martineau 
65a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
664f1654e0SMarcel Holtmann {
67a250e048SJohan Hedberg 	if (link_type == LE_LINK) {
68a250e048SJohan Hedberg 		if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
694f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
704f1654e0SMarcel Holtmann 		else
714f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
724f1654e0SMarcel Holtmann 	}
734f1654e0SMarcel Holtmann 
744f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
754f1654e0SMarcel Holtmann }
764f1654e0SMarcel Holtmann 
77a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
78a250e048SJohan Hedberg {
79a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->src_type);
80a250e048SJohan Hedberg }
81a250e048SJohan Hedberg 
82a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
83a250e048SJohan Hedberg {
84a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->dst_type);
85a250e048SJohan Hedberg }
86a250e048SJohan Hedberg 
870a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
8871ba0e56SGustavo F. Padovan 
892d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
902d792818SGustavo Padovan 						   u16 cid)
910a708f8fSGustavo F. Padovan {
923df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
93baa7e1faSGustavo F. Padovan 
943df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
953df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
963df91ea2SAndrei Emeltchenko 			return c;
970a708f8fSGustavo F. Padovan 	}
983df91ea2SAndrei Emeltchenko 	return NULL;
99baa7e1faSGustavo F. Padovan }
1000a708f8fSGustavo F. Padovan 
1012d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1022d792818SGustavo Padovan 						   u16 cid)
1030a708f8fSGustavo F. Padovan {
1043df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
105baa7e1faSGustavo F. Padovan 
1063df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1073df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
1083df91ea2SAndrei Emeltchenko 			return c;
1090a708f8fSGustavo F. Padovan 	}
1103df91ea2SAndrei Emeltchenko 	return NULL;
111baa7e1faSGustavo F. Padovan }
1120a708f8fSGustavo F. Padovan 
1130a708f8fSGustavo F. Padovan /* Find channel with given SCID.
114ef191adeSMat Martineau  * Returns locked channel. */
1152d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1162d792818SGustavo Padovan 						 u16 cid)
1170a708f8fSGustavo F. Padovan {
11848454079SGustavo F. Padovan 	struct l2cap_chan *c;
119baa7e1faSGustavo F. Padovan 
1203df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
121baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
122ef191adeSMat Martineau 	if (c)
123ef191adeSMat Martineau 		l2cap_chan_lock(c);
1243df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1253df91ea2SAndrei Emeltchenko 
12648454079SGustavo F. Padovan 	return c;
1270a708f8fSGustavo F. Padovan }
1280a708f8fSGustavo F. Padovan 
129b1a130b7SMat Martineau /* Find channel with given DCID.
130b1a130b7SMat Martineau  * Returns locked channel.
131b1a130b7SMat Martineau  */
132b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
133b1a130b7SMat Martineau 						 u16 cid)
134b1a130b7SMat Martineau {
135b1a130b7SMat Martineau 	struct l2cap_chan *c;
136b1a130b7SMat Martineau 
137b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
138b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
139b1a130b7SMat Martineau 	if (c)
140b1a130b7SMat Martineau 		l2cap_chan_lock(c);
141b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
142b1a130b7SMat Martineau 
143b1a130b7SMat Martineau 	return c;
144b1a130b7SMat Martineau }
145b1a130b7SMat Martineau 
1462d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1472d792818SGustavo Padovan 						    u8 ident)
1480a708f8fSGustavo F. Padovan {
1493df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
150baa7e1faSGustavo F. Padovan 
1513df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1523df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1533df91ea2SAndrei Emeltchenko 			return c;
1540a708f8fSGustavo F. Padovan 	}
1553df91ea2SAndrei Emeltchenko 	return NULL;
156baa7e1faSGustavo F. Padovan }
1570a708f8fSGustavo F. Padovan 
1585b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1595b155ef9SMat Martineau 						  u8 ident)
1605b155ef9SMat Martineau {
1615b155ef9SMat Martineau 	struct l2cap_chan *c;
1625b155ef9SMat Martineau 
1635b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1645b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
1655b155ef9SMat Martineau 	if (c)
1665b155ef9SMat Martineau 		l2cap_chan_lock(c);
1675b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1685b155ef9SMat Martineau 
1695b155ef9SMat Martineau 	return c;
1705b155ef9SMat Martineau }
1715b155ef9SMat Martineau 
17200f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
17300f62726SLuiz Augusto von Dentz 						      u8 src_type)
1749e4425ffSGustavo F. Padovan {
17523691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1769e4425ffSGustavo F. Padovan 
17723691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
17800f62726SLuiz Augusto von Dentz 		if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
17900f62726SLuiz Augusto von Dentz 			continue;
18000f62726SLuiz Augusto von Dentz 
18100f62726SLuiz Augusto von Dentz 		if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
18200f62726SLuiz Augusto von Dentz 			continue;
18300f62726SLuiz Augusto von Dentz 
1847eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
18523691d75SGustavo F. Padovan 			return c;
1869e4425ffSGustavo F. Padovan 	}
187250938cbSSzymon Janc 	return NULL;
188250938cbSSzymon Janc }
1899e4425ffSGustavo F. Padovan 
1909e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
1919e4425ffSGustavo F. Padovan {
19273b2ec18SGustavo F. Padovan 	int err;
19373b2ec18SGustavo F. Padovan 
194333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
1959e4425ffSGustavo F. Padovan 
19600f62726SLuiz Augusto von Dentz 	if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
19773b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
19873b2ec18SGustavo F. Padovan 		goto done;
1999e4425ffSGustavo F. Padovan 	}
2009e4425ffSGustavo F. Padovan 
20173b2ec18SGustavo F. Padovan 	if (psm) {
2029e4425ffSGustavo F. Padovan 		chan->psm = psm;
2039e4425ffSGustavo F. Padovan 		chan->sport = psm;
20473b2ec18SGustavo F. Padovan 		err = 0;
20573b2ec18SGustavo F. Padovan 	} else {
20692594a51SJohan Hedberg 		u16 p, start, end, incr;
20792594a51SJohan Hedberg 
20892594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
20992594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
21092594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
21192594a51SJohan Hedberg 			incr = 2;
21292594a51SJohan Hedberg 		} else {
21392594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
21492594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
21592594a51SJohan Hedberg 			incr = 1;
21692594a51SJohan Hedberg 		}
2179e4425ffSGustavo F. Padovan 
21873b2ec18SGustavo F. Padovan 		err = -EINVAL;
21992594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
22000f62726SLuiz Augusto von Dentz 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
22100f62726SLuiz Augusto von Dentz 							 chan->src_type)) {
22273b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
22373b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
22473b2ec18SGustavo F. Padovan 				err = 0;
22573b2ec18SGustavo F. Padovan 				break;
22673b2ec18SGustavo F. Padovan 			}
22773b2ec18SGustavo F. Padovan 	}
22873b2ec18SGustavo F. Padovan 
22973b2ec18SGustavo F. Padovan done:
230333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
23173b2ec18SGustavo F. Padovan 	return err;
2329e4425ffSGustavo F. Padovan }
2336b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2349e4425ffSGustavo F. Padovan 
2359e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2369e4425ffSGustavo F. Padovan {
237333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2389e4425ffSGustavo F. Padovan 
23914824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
24014824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
24114824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
24214824308SJohan Hedberg 
2439e4425ffSGustavo F. Padovan 	chan->scid = scid;
2449e4425ffSGustavo F. Padovan 
245333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2469e4425ffSGustavo F. Padovan 
2479e4425ffSGustavo F. Padovan 	return 0;
2489e4425ffSGustavo F. Padovan }
2499e4425ffSGustavo F. Padovan 
250baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2510a708f8fSGustavo F. Padovan {
252e77af755SJohan Hedberg 	u16 cid, dyn_end;
2530a708f8fSGustavo F. Padovan 
254e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
255e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
256e77af755SJohan Hedberg 	else
257e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
258e77af755SJohan Hedberg 
259ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
260baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2610a708f8fSGustavo F. Padovan 			return cid;
2620a708f8fSGustavo F. Padovan 	}
2630a708f8fSGustavo F. Padovan 
2640a708f8fSGustavo F. Padovan 	return 0;
2650a708f8fSGustavo F. Padovan }
2660a708f8fSGustavo F. Padovan 
267f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
26889bc500eSGustavo F. Padovan {
26942d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
270badaaa00SGustavo F. Padovan 	       state_to_string(state));
271badaaa00SGustavo F. Padovan 
27289bc500eSGustavo F. Padovan 	chan->state = state;
27353f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
27489bc500eSGustavo F. Padovan }
27589bc500eSGustavo F. Padovan 
276f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
277f8e73017SGustavo Padovan 						int state, int err)
2782e0052e4SAndrei Emeltchenko {
279f8e73017SGustavo Padovan 	chan->state = state;
28053f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2812e0052e4SAndrei Emeltchenko }
2822e0052e4SAndrei Emeltchenko 
2832e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
2842e0052e4SAndrei Emeltchenko {
285f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2862e0052e4SAndrei Emeltchenko }
2872e0052e4SAndrei Emeltchenko 
2884239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
2894239d16fSMat Martineau {
2904239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
2914239d16fSMat Martineau 	    chan->retrans_timeout) {
2924239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
2934239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
2944239d16fSMat Martineau 	}
2954239d16fSMat Martineau }
2964239d16fSMat Martineau 
2974239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
2984239d16fSMat Martineau {
2994239d16fSMat Martineau 	__clear_retrans_timer(chan);
3004239d16fSMat Martineau 	if (chan->monitor_timeout) {
3014239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
3024239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
3034239d16fSMat Martineau 	}
3044239d16fSMat Martineau }
3054239d16fSMat Martineau 
306608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
307608bcc6dSMat Martineau 					       u16 seq)
308608bcc6dSMat Martineau {
309608bcc6dSMat Martineau 	struct sk_buff *skb;
310608bcc6dSMat Martineau 
311608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
312a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
313608bcc6dSMat Martineau 			return skb;
314608bcc6dSMat Martineau 	}
315608bcc6dSMat Martineau 
316608bcc6dSMat Martineau 	return NULL;
317608bcc6dSMat Martineau }
318608bcc6dSMat Martineau 
3193c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3203c588192SMat Martineau 
3213c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3223c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3233c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3243c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3253c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3263c588192SMat Martineau  * and removed from the head in constant time, without further memory
3273c588192SMat Martineau  * allocs or frees.
3283c588192SMat Martineau  */
3293c588192SMat Martineau 
3303c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3313c588192SMat Martineau {
3323c588192SMat Martineau 	size_t alloc_size, i;
3333c588192SMat Martineau 
3343c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3353c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3363c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3373c588192SMat Martineau 	 */
3383c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3393c588192SMat Martineau 
3406da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3413c588192SMat Martineau 	if (!seq_list->list)
3423c588192SMat Martineau 		return -ENOMEM;
3433c588192SMat Martineau 
3443c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3453c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3463c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3473c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3483c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3493c588192SMat Martineau 
3503c588192SMat Martineau 	return 0;
3513c588192SMat Martineau }
3523c588192SMat Martineau 
3533c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3543c588192SMat Martineau {
3553c588192SMat Martineau 	kfree(seq_list->list);
3563c588192SMat Martineau }
3573c588192SMat Martineau 
3583c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3593c588192SMat Martineau 					   u16 seq)
3603c588192SMat Martineau {
3613c588192SMat Martineau 	/* Constant-time check for list membership */
3623c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3633c588192SMat Martineau }
3643c588192SMat Martineau 
36503a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3663c588192SMat Martineau {
36703a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3683c588192SMat Martineau 	u16 mask = seq_list->mask;
3693c588192SMat Martineau 
3703c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3713c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3723c588192SMat Martineau 
3733c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3743c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3753c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3763c588192SMat Martineau 	}
3773c588192SMat Martineau 
3783c588192SMat Martineau 	return seq;
3793c588192SMat Martineau }
3803c588192SMat Martineau 
3813c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3823c588192SMat Martineau {
3833c588192SMat Martineau 	u16 i;
384f522ae36SGustavo Padovan 
385f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
386f522ae36SGustavo Padovan 		return;
387f522ae36SGustavo Padovan 
3883c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
3893c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3903c588192SMat Martineau 
3913c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3923c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3933c588192SMat Martineau }
3943c588192SMat Martineau 
3953c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
3963c588192SMat Martineau {
3973c588192SMat Martineau 	u16 mask = seq_list->mask;
3983c588192SMat Martineau 
3993c588192SMat Martineau 	/* All appends happen in constant time */
4003c588192SMat Martineau 
401f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
402f522ae36SGustavo Padovan 		return;
403f522ae36SGustavo Padovan 
4043c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4053c588192SMat Martineau 		seq_list->head = seq;
4063c588192SMat Martineau 	else
4073c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
4083c588192SMat Martineau 
4093c588192SMat Martineau 	seq_list->tail = seq;
4103c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4113c588192SMat Martineau }
4123c588192SMat Martineau 
413721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
414ab07801dSGustavo F. Padovan {
415721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
416721c4181SGustavo F. Padovan 					       chan_timer.work);
4173df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
418ab07801dSGustavo F. Padovan 	int reason;
419ab07801dSGustavo F. Padovan 
420e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
421ab07801dSGustavo F. Padovan 
4223df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4236c08fc89SManish Mandlik 	/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4246c08fc89SManish Mandlik 	 * this work. No need to call l2cap_chan_hold(chan) here again.
4256c08fc89SManish Mandlik 	 */
4266be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
427ab07801dSGustavo F. Padovan 
42889bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
429ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
43089bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
431ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
432ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
433ab07801dSGustavo F. Padovan 	else
434ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
435ab07801dSGustavo F. Padovan 
4360f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
437ab07801dSGustavo F. Padovan 
43880b98027SGustavo Padovan 	chan->ops->close(chan);
4393df91ea2SAndrei Emeltchenko 
4406c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
441371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4426c08fc89SManish Mandlik 
4436c08fc89SManish Mandlik 	mutex_unlock(&conn->chan_lock);
444ab07801dSGustavo F. Padovan }
445ab07801dSGustavo F. Padovan 
446eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4470a708f8fSGustavo F. Padovan {
44848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4490a708f8fSGustavo F. Padovan 
45048454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
45148454079SGustavo F. Padovan 	if (!chan)
45248454079SGustavo F. Padovan 		return NULL;
4530a708f8fSGustavo F. Padovan 
454*be859723STetsuo Handa 	skb_queue_head_init(&chan->tx_q);
455*be859723STetsuo Handa 	skb_queue_head_init(&chan->srej_q);
456c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
457c03b355eSAndrei Emeltchenko 
458ff714119SJohan Hedberg 	/* Set default lock nesting level */
459ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
460ff714119SJohan Hedberg 
461333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
46223691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
463333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
46423691d75SGustavo F. Padovan 
465721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
466ab07801dSGustavo F. Padovan 
46789bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
46889bc500eSGustavo F. Padovan 
469144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
47071ba0e56SGustavo F. Padovan 
4712827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4722827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4732827011fSMat Martineau 
474eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
475abc545b8SSzymon Janc 
47648454079SGustavo F. Padovan 	return chan;
4770a708f8fSGustavo F. Padovan }
4786b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4790a708f8fSGustavo F. Padovan 
480144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
4816ff5abbfSGustavo F. Padovan {
482144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
483144ad330SSyam Sidhardhan 
4844af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
4854af66c69SJaganath Kanakkassery 
486333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
48723691d75SGustavo F. Padovan 	list_del(&chan->global_l);
488333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
48923691d75SGustavo F. Padovan 
4904af66c69SJaganath Kanakkassery 	kfree(chan);
4916ff5abbfSGustavo F. Padovan }
4926ff5abbfSGustavo F. Padovan 
49330648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
49430648372SJaganath Kanakkassery {
4952c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
49630648372SJaganath Kanakkassery 
497144ad330SSyam Sidhardhan 	kref_get(&c->kref);
49830648372SJaganath Kanakkassery }
49930648372SJaganath Kanakkassery 
50030648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
50130648372SJaganath Kanakkassery {
5022c935bc5SPeter Zijlstra 	BT_DBG("chan %p orig refcnt %d", c, kref_read(&c->kref));
50330648372SJaganath Kanakkassery 
504144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
50530648372SJaganath Kanakkassery }
5066b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
50730648372SJaganath Kanakkassery 
508bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
509bd4b1653SAndrei Emeltchenko {
510bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
511bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
512bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
513bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5146a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5156a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
516c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
517bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5186a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5196a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5206a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5213a9d54b1SArchie Pusaka 
5226a5e8165SJukka Rissanen 	chan->conf_state = 0;
5233a9d54b1SArchie Pusaka 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
524bd4b1653SAndrei Emeltchenko 
525bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
526bd4b1653SAndrei Emeltchenko }
5276b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
528bd4b1653SAndrei Emeltchenko 
529ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
53038319713SJohan Hedberg {
5310ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5320ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5330ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
534ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
535fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
536fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
53796cd8eaaSLuiz Augusto von Dentz 	/* Give enough credits for a full packet */
53896cd8eaaSLuiz Augusto von Dentz 	chan->rx_credits = (chan->imtu / chan->mps) + 1;
5390ce43ce6SJohan Hedberg 
5400ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
54138319713SJohan Hedberg }
54238319713SJohan Hedberg 
54315f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
54415f02b91SLuiz Augusto von Dentz {
54515f02b91SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, tx_credits);
54615f02b91SLuiz Augusto von Dentz 
54715f02b91SLuiz Augusto von Dentz 	/* L2CAP implementations shall support a minimum MPS of 64 octets */
54815f02b91SLuiz Augusto von Dentz 	if (chan->mps < L2CAP_ECRED_MIN_MPS) {
54915f02b91SLuiz Augusto von Dentz 		chan->mps = L2CAP_ECRED_MIN_MPS;
55015f02b91SLuiz Augusto von Dentz 		chan->rx_credits = (chan->imtu / chan->mps) + 1;
55115f02b91SLuiz Augusto von Dentz 	}
55215f02b91SLuiz Augusto von Dentz }
55315f02b91SLuiz Augusto von Dentz 
55493c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5550a708f8fSGustavo F. Padovan {
5560a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
557097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5580a708f8fSGustavo F. Padovan 
5599f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5600a708f8fSGustavo F. Padovan 
5618c1d787bSGustavo F. Padovan 	chan->conn = conn;
5620a708f8fSGustavo F. Padovan 
5635491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5645491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
5650a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
566fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
56721626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
5680c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
5695491120eSAndrei Emeltchenko 		break;
5705491120eSAndrei Emeltchenko 
5715491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
5720a708f8fSGustavo F. Padovan 		/* Connectionless socket */
573fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
574fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
5750c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5765491120eSAndrei Emeltchenko 		break;
5775491120eSAndrei Emeltchenko 
5782338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
5792338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
580416fa752SAndrei Emeltchenko 		break;
581416fa752SAndrei Emeltchenko 
5825491120eSAndrei Emeltchenko 	default:
5830a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
584fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
585fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
5860c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
5870a708f8fSGustavo F. Padovan 	}
5880a708f8fSGustavo F. Padovan 
5898f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
5908f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
5918f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
5928f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
5938f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
5948936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
5958f7975b1SAndrei Emeltchenko 
596371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
597baa7e1faSGustavo F. Padovan 
598c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
599c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
600c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
6015ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
6025ee9891dSJohan Hedberg 
6033df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
604643162a8SAndrei Emeltchenko }
605643162a8SAndrei Emeltchenko 
606466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
607643162a8SAndrei Emeltchenko {
608643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
609643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
6103df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
6110a708f8fSGustavo F. Padovan }
6120a708f8fSGustavo F. Padovan 
613466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6140a708f8fSGustavo F. Padovan {
6158c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6160a708f8fSGustavo F. Padovan 
617c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
6180a708f8fSGustavo F. Padovan 
61949d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
62049d11741SJohan Hedberg 	       state_to_string(chan->state));
6210a708f8fSGustavo F. Padovan 
62272847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
62372847ce0SJohan Hedberg 
6240a708f8fSGustavo F. Padovan 	if (conn) {
62556f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
626baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6273df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6283d57dc68SGustavo F. Padovan 
629371fd835SUlisses Furquim 		l2cap_chan_put(chan);
630baa7e1faSGustavo F. Padovan 
6318c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6323cabbfdaSAndrei Emeltchenko 
633c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
634c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
635c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
636c16900cfSJohan Hedberg 		 */
637c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
638c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
63976a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
64056f60984SAndrei Emeltchenko 
64156f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
64256f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6430a708f8fSGustavo F. Padovan 	}
6440a708f8fSGustavo F. Padovan 
645419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
646419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
647419e08c1SAndrei Emeltchenko 
648419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
649419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
650419e08c1SAndrei Emeltchenko 	}
651419e08c1SAndrei Emeltchenko 
6522827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6536ff5abbfSGustavo F. Padovan 		return;
6542ead70b8SGustavo F. Padovan 
655ee556f66SGustavo Padovan 	switch(chan->mode) {
656ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
657ee556f66SGustavo Padovan 		break;
6580a708f8fSGustavo F. Padovan 
65938319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
66015f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
661177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
66238319713SJohan Hedberg 		break;
66338319713SJohan Hedberg 
664ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6651a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6661a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6671a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6680a708f8fSGustavo F. Padovan 
669f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6700a708f8fSGustavo F. Padovan 
6713c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
6723c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
67319186c7bSGustavo A. R. Silva 		fallthrough;
674ee556f66SGustavo Padovan 
675ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
676ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
677ee556f66SGustavo Padovan 		break;
6780a708f8fSGustavo F. Padovan 	}
679ee556f66SGustavo Padovan 
680ee556f66SGustavo Padovan 	return;
6810a708f8fSGustavo F. Padovan }
6826b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
6830a708f8fSGustavo F. Padovan 
684da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
685da49b602SLuiz Augusto von Dentz 			      void *data)
686da49b602SLuiz Augusto von Dentz {
687da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
688da49b602SLuiz Augusto von Dentz 
689da49b602SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
690da49b602SLuiz Augusto von Dentz 		func(chan, data);
691da49b602SLuiz Augusto von Dentz 	}
692da49b602SLuiz Augusto von Dentz }
693da49b602SLuiz Augusto von Dentz 
694da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
695da49b602SLuiz Augusto von Dentz 		     void *data)
696da49b602SLuiz Augusto von Dentz {
697da49b602SLuiz Augusto von Dentz 	if (!conn)
698da49b602SLuiz Augusto von Dentz 		return;
699da49b602SLuiz Augusto von Dentz 
700da49b602SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
701da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, func, data);
702da49b602SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
703da49b602SLuiz Augusto von Dentz }
704da49b602SLuiz Augusto von Dentz 
705da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
706da49b602SLuiz Augusto von Dentz 
707f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
708387a33e3SJohan Hedberg {
709f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
710f3d82d0cSJohan Hedberg 					       id_addr_update_work);
711f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
712387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
713387a33e3SJohan Hedberg 
714387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
715387a33e3SJohan Hedberg 
716387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
717387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
718387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
719a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
720387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
721387a33e3SJohan Hedberg 	}
722387a33e3SJohan Hedberg 
723387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
724387a33e3SJohan Hedberg }
725387a33e3SJohan Hedberg 
72627e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
72727e2d4c8SJohan Hedberg {
72827e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
72927e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
73027e2d4c8SJohan Hedberg 	u16 result;
73127e2d4c8SJohan Hedberg 
73227e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
733571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
73427e2d4c8SJohan Hedberg 	else
735571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
73627e2d4c8SJohan Hedberg 
73727e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
73827e2d4c8SJohan Hedberg 
73927e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
74027e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
7413916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
7420cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
74327e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
74427e2d4c8SJohan Hedberg 
74527e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
74627e2d4c8SJohan Hedberg 		       &rsp);
74727e2d4c8SJohan Hedberg }
74827e2d4c8SJohan Hedberg 
74915f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
75015f02b91SLuiz Augusto von Dentz {
75115f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
75215f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp rsp;
75315f02b91SLuiz Augusto von Dentz 	u16 result;
75415f02b91SLuiz Augusto von Dentz 
75515f02b91SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
75615f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHORIZATION;
75715f02b91SLuiz Augusto von Dentz 	else
75815f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
75915f02b91SLuiz Augusto von Dentz 
76015f02b91SLuiz Augusto von Dentz 	l2cap_state_change(chan, BT_DISCONN);
76115f02b91SLuiz Augusto von Dentz 
76215f02b91SLuiz Augusto von Dentz 	memset(&rsp, 0, sizeof(rsp));
76315f02b91SLuiz Augusto von Dentz 
76415f02b91SLuiz Augusto von Dentz 	rsp.result  = cpu_to_le16(result);
76515f02b91SLuiz Augusto von Dentz 
76615f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
76715f02b91SLuiz Augusto von Dentz 		       &rsp);
76815f02b91SLuiz Augusto von Dentz }
76915f02b91SLuiz Augusto von Dentz 
770791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
771791d60f7SJohan Hedberg {
772791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
773791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
774791d60f7SJohan Hedberg 	u16 result;
775791d60f7SJohan Hedberg 
776791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
777791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
778791d60f7SJohan Hedberg 	else
779791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
780791d60f7SJohan Hedberg 
781791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
782791d60f7SJohan Hedberg 
783791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
784791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
785791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
786dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
787791d60f7SJohan Hedberg 
788791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
789791d60f7SJohan Hedberg }
790791d60f7SJohan Hedberg 
7910f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
7924519de9aSGustavo F. Padovan {
7934519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
7944519de9aSGustavo F. Padovan 
7957eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
7964519de9aSGustavo F. Padovan 
79789bc500eSGustavo F. Padovan 	switch (chan->state) {
7984519de9aSGustavo F. Padovan 	case BT_LISTEN:
799c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8004519de9aSGustavo F. Padovan 		break;
8014519de9aSGustavo F. Padovan 
8024519de9aSGustavo F. Padovan 	case BT_CONNECTED:
8034519de9aSGustavo F. Padovan 	case BT_CONFIG:
8047b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8058d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8065e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
8074519de9aSGustavo F. Padovan 		} else
8084519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
8094519de9aSGustavo F. Padovan 		break;
8104519de9aSGustavo F. Padovan 
8114519de9aSGustavo F. Padovan 	case BT_CONNECT2:
812791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
813791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
814791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
81515f02b91SLuiz Augusto von Dentz 			else if (conn->hcon->type == LE_LINK) {
81615f02b91SLuiz Augusto von Dentz 				switch (chan->mode) {
81715f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_LE_FLOWCTL:
81827e2d4c8SJohan Hedberg 					l2cap_chan_le_connect_reject(chan);
81915f02b91SLuiz Augusto von Dentz 					break;
82015f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_EXT_FLOWCTL:
82115f02b91SLuiz Augusto von Dentz 					l2cap_chan_ecred_connect_reject(chan);
82215f02b91SLuiz Augusto von Dentz 					break;
82315f02b91SLuiz Augusto von Dentz 				}
82415f02b91SLuiz Augusto von Dentz 			}
8254519de9aSGustavo F. Padovan 		}
8264519de9aSGustavo F. Padovan 
8274519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8284519de9aSGustavo F. Padovan 		break;
8294519de9aSGustavo F. Padovan 
8304519de9aSGustavo F. Padovan 	case BT_CONNECT:
8314519de9aSGustavo F. Padovan 	case BT_DISCONN:
8324519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8334519de9aSGustavo F. Padovan 		break;
8344519de9aSGustavo F. Padovan 
8354519de9aSGustavo F. Padovan 	default:
836c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8374519de9aSGustavo F. Padovan 		break;
8384519de9aSGustavo F. Padovan 	}
8394519de9aSGustavo F. Padovan }
8406b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8414519de9aSGustavo F. Padovan 
8424343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8430a708f8fSGustavo F. Padovan {
8446a974b50SMarcel Holtmann 	switch (chan->chan_type) {
8456a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
8464343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8470a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8487d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8490a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
8500a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8510a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
8520a708f8fSGustavo F. Padovan 		default:
8530a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8540a708f8fSGustavo F. Padovan 		}
8556a974b50SMarcel Holtmann 		break;
8563124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
857dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8583124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
8593124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
8603124b843SMarcel Holtmann 		}
8617d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
8627d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
8633124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
8643124b843SMarcel Holtmann 		else
8653124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
8663124b843SMarcel Holtmann 		break;
8676a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
868dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8694343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
8704343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
8710a708f8fSGustavo F. Padovan 
8727d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
8737d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
8740a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
8750a708f8fSGustavo F. Padovan 			else
8760a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
8776a974b50SMarcel Holtmann 		}
87819186c7bSGustavo A. R. Silva 		fallthrough;
87919186c7bSGustavo A. R. Silva 
8806a974b50SMarcel Holtmann 	default:
8814343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8820a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8837d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8840a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
8850a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8860a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
8870a708f8fSGustavo F. Padovan 		default:
8880a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8890a708f8fSGustavo F. Padovan 		}
8906a974b50SMarcel Holtmann 		break;
8910a708f8fSGustavo F. Padovan 	}
8920a708f8fSGustavo F. Padovan }
8930a708f8fSGustavo F. Padovan 
8940a708f8fSGustavo F. Padovan /* Service level security */
895e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
8960a708f8fSGustavo F. Padovan {
8978c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8980a708f8fSGustavo F. Padovan 	__u8 auth_type;
8990a708f8fSGustavo F. Padovan 
900a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
901a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
902a17de2feSJohan Hedberg 
9034343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
9040a708f8fSGustavo F. Padovan 
905e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
906e7cafc45SJohan Hedberg 				 initiator);
9070a708f8fSGustavo F. Padovan }
9080a708f8fSGustavo F. Padovan 
909b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9100a708f8fSGustavo F. Padovan {
9110a708f8fSGustavo F. Padovan 	u8 id;
9120a708f8fSGustavo F. Padovan 
9130a708f8fSGustavo F. Padovan 	/* Get next available identificator.
9140a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
9150a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
9160a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
9170a708f8fSGustavo F. Padovan 	 */
9180a708f8fSGustavo F. Padovan 
9195a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
9200a708f8fSGustavo F. Padovan 
9210a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
9220a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
9230a708f8fSGustavo F. Padovan 
9240a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
9250a708f8fSGustavo F. Padovan 
9265a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
9270a708f8fSGustavo F. Padovan 
9280a708f8fSGustavo F. Padovan 	return id;
9290a708f8fSGustavo F. Padovan }
9300a708f8fSGustavo F. Padovan 
9312d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9322d792818SGustavo Padovan 			   void *data)
9330a708f8fSGustavo F. Padovan {
9340a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9350a708f8fSGustavo F. Padovan 	u8 flags;
9360a708f8fSGustavo F. Padovan 
9370a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
9380a708f8fSGustavo F. Padovan 
9390a708f8fSGustavo F. Padovan 	if (!skb)
9400a708f8fSGustavo F. Padovan 		return;
9410a708f8fSGustavo F. Padovan 
942f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
943f6af675eSSteven Walter 	 * not support auto-flushing packets) */
944f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
945f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
9460a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
9470a708f8fSGustavo F. Padovan 	else
9480a708f8fSGustavo F. Padovan 		flags = ACL_START;
9490a708f8fSGustavo F. Padovan 
95014b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9515e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
95214b12d0bSJaikumar Ganesh 
95373d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
9540a708f8fSGustavo F. Padovan }
9550a708f8fSGustavo F. Padovan 
95602b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
95702b0fbb9SMat Martineau {
95802b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
95902b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
96002b0fbb9SMat Martineau }
96102b0fbb9SMat Martineau 
96273d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
96373d80debSLuiz Augusto von Dentz {
96473d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
96573d80debSLuiz Augusto von Dentz 	u16 flags;
96673d80debSLuiz Augusto von Dentz 
96773d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
96873d80debSLuiz Augusto von Dentz 	       skb->priority);
96973d80debSLuiz Augusto von Dentz 
970d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
971d5f8a75dSMat Martineau 		if (chan->hs_hchan)
972d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
973d5f8a75dSMat Martineau 		else
974d5f8a75dSMat Martineau 			kfree_skb(skb);
975d5f8a75dSMat Martineau 
976d5f8a75dSMat Martineau 		return;
977d5f8a75dSMat Martineau 	}
978d5f8a75dSMat Martineau 
979f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
980f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
981f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
982f6af675eSSteven Walter 	 */
983f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
984f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
985f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
98673d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
98773d80debSLuiz Augusto von Dentz 	else
98873d80debSLuiz Augusto von Dentz 		flags = ACL_START;
98973d80debSLuiz Augusto von Dentz 
99073d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
99173d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
9920a708f8fSGustavo F. Padovan }
9930a708f8fSGustavo F. Padovan 
994b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
995b5c6aaedSMat Martineau {
996b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
997b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
998b5c6aaedSMat Martineau 
999b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
1000b5c6aaedSMat Martineau 		/* S-Frame */
1001b5c6aaedSMat Martineau 		control->sframe = 1;
1002b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1003b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
1004b5c6aaedSMat Martineau 
1005b5c6aaedSMat Martineau 		control->sar = 0;
1006b5c6aaedSMat Martineau 		control->txseq = 0;
1007b5c6aaedSMat Martineau 	} else {
1008b5c6aaedSMat Martineau 		/* I-Frame */
1009b5c6aaedSMat Martineau 		control->sframe = 0;
1010b5c6aaedSMat Martineau 		control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1011b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
1012b5c6aaedSMat Martineau 
1013b5c6aaedSMat Martineau 		control->poll = 0;
1014b5c6aaedSMat Martineau 		control->super = 0;
1015b5c6aaedSMat Martineau 	}
1016b5c6aaedSMat Martineau }
1017b5c6aaedSMat Martineau 
1018b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1019b5c6aaedSMat Martineau {
1020b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1021b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1022b5c6aaedSMat Martineau 
1023b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1024b5c6aaedSMat Martineau 		/* S-Frame */
1025b5c6aaedSMat Martineau 		control->sframe = 1;
1026b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1027b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1028b5c6aaedSMat Martineau 
1029b5c6aaedSMat Martineau 		control->sar = 0;
1030b5c6aaedSMat Martineau 		control->txseq = 0;
1031b5c6aaedSMat Martineau 	} else {
1032b5c6aaedSMat Martineau 		/* I-Frame */
1033b5c6aaedSMat Martineau 		control->sframe = 0;
1034b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1035b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1036b5c6aaedSMat Martineau 
1037b5c6aaedSMat Martineau 		control->poll = 0;
1038b5c6aaedSMat Martineau 		control->super = 0;
1039b5c6aaedSMat Martineau 	}
1040b5c6aaedSMat Martineau }
1041b5c6aaedSMat Martineau 
1042b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1043b5c6aaedSMat Martineau 				    struct sk_buff *skb)
1044b5c6aaedSMat Martineau {
1045b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1046b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
1047a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1048cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1049b5c6aaedSMat Martineau 	} else {
1050b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
1051a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1052cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1053b5c6aaedSMat Martineau 	}
1054b5c6aaedSMat Martineau }
1055b5c6aaedSMat Martineau 
1056b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1057b5c6aaedSMat Martineau {
1058b5c6aaedSMat Martineau 	u32 packed;
1059b5c6aaedSMat Martineau 
1060b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1061b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1062b5c6aaedSMat Martineau 
1063b5c6aaedSMat Martineau 	if (control->sframe) {
1064b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1065b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1066b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1067b5c6aaedSMat Martineau 	} else {
1068b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
1069b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1070b5c6aaedSMat Martineau 	}
1071b5c6aaedSMat Martineau 
1072b5c6aaedSMat Martineau 	return packed;
1073b5c6aaedSMat Martineau }
1074b5c6aaedSMat Martineau 
1075b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1076b5c6aaedSMat Martineau {
1077b5c6aaedSMat Martineau 	u16 packed;
1078b5c6aaedSMat Martineau 
1079b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1080b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1081b5c6aaedSMat Martineau 
1082b5c6aaedSMat Martineau 	if (control->sframe) {
1083b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1084b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1085b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1086b5c6aaedSMat Martineau 	} else {
1087b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1088b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1089b5c6aaedSMat Martineau 	}
1090b5c6aaedSMat Martineau 
1091b5c6aaedSMat Martineau 	return packed;
1092b5c6aaedSMat Martineau }
1093b5c6aaedSMat Martineau 
1094b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1095b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1096b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1097b5c6aaedSMat Martineau {
1098b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1099b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1100b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1101b5c6aaedSMat Martineau 	} else {
1102b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1103b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1104b5c6aaedSMat Martineau 	}
1105b5c6aaedSMat Martineau }
1106b5c6aaedSMat Martineau 
1107ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1108ba7aa64fSGustavo Padovan {
1109ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1110ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1111ba7aa64fSGustavo Padovan 	else
1112ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1113ba7aa64fSGustavo Padovan }
1114ba7aa64fSGustavo Padovan 
1115a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1116a67d7f6fSMat Martineau 					       u32 control)
11170a708f8fSGustavo F. Padovan {
11180a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
11190a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1120ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
11210a708f8fSGustavo F. Padovan 
11220a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
112303a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
11240a708f8fSGustavo F. Padovan 
1125a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
11260a708f8fSGustavo F. Padovan 
11270a708f8fSGustavo F. Padovan 	if (!skb)
1128a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
11290a708f8fSGustavo F. Padovan 
11304df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
11310a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1132fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
113388843ab0SAndrei Emeltchenko 
1134a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1135a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1136a67d7f6fSMat Martineau 	else
1137a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11380a708f8fSGustavo F. Padovan 
113947d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1140a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
114103a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
11420a708f8fSGustavo F. Padovan 	}
11430a708f8fSGustavo F. Padovan 
114473d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1145a67d7f6fSMat Martineau 	return skb;
1146a67d7f6fSMat Martineau }
1147a67d7f6fSMat Martineau 
1148a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1149a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1150a67d7f6fSMat Martineau {
1151a67d7f6fSMat Martineau 	struct sk_buff *skb;
1152a67d7f6fSMat Martineau 	u32 control_field;
1153a67d7f6fSMat Martineau 
1154a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1155a67d7f6fSMat Martineau 
1156a67d7f6fSMat Martineau 	if (!control->sframe)
1157a67d7f6fSMat Martineau 		return;
1158a67d7f6fSMat Martineau 
1159b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1160b99e13adSMat Martineau 		return;
1161b99e13adSMat Martineau 
1162a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1163a67d7f6fSMat Martineau 	    !control->poll)
1164a67d7f6fSMat Martineau 		control->final = 1;
1165a67d7f6fSMat Martineau 
1166a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1167a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1168a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1169a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1170a67d7f6fSMat Martineau 
1171a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1172a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1173a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1174a67d7f6fSMat Martineau 	}
1175a67d7f6fSMat Martineau 
1176a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1177a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1178a67d7f6fSMat Martineau 
1179a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1180a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1181a67d7f6fSMat Martineau 	else
1182a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1183a67d7f6fSMat Martineau 
1184a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1185a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
118673d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
11870a708f8fSGustavo F. Padovan }
11880a708f8fSGustavo F. Padovan 
1189c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
11900a708f8fSGustavo F. Padovan {
1191c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
11920a708f8fSGustavo F. Padovan 
1193c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1194c9e3d5e0SMat Martineau 
1195c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1196c9e3d5e0SMat Martineau 	control.sframe = 1;
1197c9e3d5e0SMat Martineau 	control.poll = poll;
1198c9e3d5e0SMat Martineau 
1199c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1200c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1201c9e3d5e0SMat Martineau 	else
1202c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1203c9e3d5e0SMat Martineau 
1204c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1205c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
12060a708f8fSGustavo F. Padovan }
12070a708f8fSGustavo F. Padovan 
1208b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12090a708f8fSGustavo F. Padovan {
12105ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12115ff6f34dSJohan Hedberg 		return true;
12125ff6f34dSJohan Hedberg 
1213c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12140a708f8fSGustavo F. Padovan }
12150a708f8fSGustavo F. Padovan 
121693c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
121793c3e8f5SAndrei Emeltchenko {
121893c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12191df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
12201df7b17aSMarcel Holtmann 	bool amp_available = false;
122193c3e8f5SAndrei Emeltchenko 
12220bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
12231df7b17aSMarcel Holtmann 		return false;
12241df7b17aSMarcel Holtmann 
12250bd49fc7SJohan Hedberg 	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
12261df7b17aSMarcel Holtmann 		return false;
12271df7b17aSMarcel Holtmann 
12281df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
12291df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
12301df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
12311df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
12321df7b17aSMarcel Holtmann 			amp_available = true;
12331df7b17aSMarcel Holtmann 			break;
12341df7b17aSMarcel Holtmann 		}
12351df7b17aSMarcel Holtmann 	}
12361df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
12371df7b17aSMarcel Holtmann 
12381df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
12391df7b17aSMarcel Holtmann 		return amp_available;
1240848566b3SMarcel Holtmann 
124193c3e8f5SAndrei Emeltchenko 	return false;
124293c3e8f5SAndrei Emeltchenko }
124393c3e8f5SAndrei Emeltchenko 
12445ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
12455ce66b59SAndrei Emeltchenko {
12465ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
12475ce66b59SAndrei Emeltchenko 	return true;
12485ce66b59SAndrei Emeltchenko }
12495ce66b59SAndrei Emeltchenko 
12502766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12519b27f350SAndrei Emeltchenko {
12529b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12539b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
12549b27f350SAndrei Emeltchenko 
12559b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
12569b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
12579b27f350SAndrei Emeltchenko 
12589b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
12599b27f350SAndrei Emeltchenko 
12609b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12619b27f350SAndrei Emeltchenko 
12629b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12639b27f350SAndrei Emeltchenko }
12649b27f350SAndrei Emeltchenko 
12658eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
12668eb200bdSMat Martineau {
12678eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
12688eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
12698eb200bdSMat Martineau 	req.psm  = chan->psm;
12708eb200bdSMat Martineau 	req.amp_id = amp_id;
12718eb200bdSMat Martineau 
12728eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
12738eb200bdSMat Martineau 
12748eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
12758eb200bdSMat Martineau 		       sizeof(req), &req);
12768eb200bdSMat Martineau }
12778eb200bdSMat Martineau 
127802b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
127902b0fbb9SMat Martineau {
128002b0fbb9SMat Martineau 	struct sk_buff *skb;
128102b0fbb9SMat Martineau 
128202b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
128302b0fbb9SMat Martineau 
128402b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
128502b0fbb9SMat Martineau 		return;
128602b0fbb9SMat Martineau 
128702b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
128802b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
128902b0fbb9SMat Martineau 	__clear_ack_timer(chan);
129002b0fbb9SMat Martineau 
129102b0fbb9SMat Martineau 	chan->retry_count = 0;
129202b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
1293a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.retries)
1294a4368ff3SJohan Hedberg 			bt_cb(skb)->l2cap.retries = 1;
129502b0fbb9SMat Martineau 		else
129602b0fbb9SMat Martineau 			break;
129702b0fbb9SMat Martineau 	}
129802b0fbb9SMat Martineau 
129902b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
130002b0fbb9SMat Martineau 
130102b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
130202b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
130302b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
130402b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
130502b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
130602b0fbb9SMat Martineau 
130702b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
130802b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
130902b0fbb9SMat Martineau 
131002b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
131102b0fbb9SMat Martineau }
131202b0fbb9SMat Martineau 
13135f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
13145f3847a4SMat Martineau {
13155f3847a4SMat Martineau 	u8 move_role = chan->move_role;
13165f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
13175f3847a4SMat Martineau 
13185f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
13195f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
13205f3847a4SMat Martineau 
13215f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
13225f3847a4SMat Martineau 		return;
13235f3847a4SMat Martineau 
13245f3847a4SMat Martineau 	switch (move_role) {
13255f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
13265f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
13275f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
13285f3847a4SMat Martineau 		break;
13295f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
13305f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
13315f3847a4SMat Martineau 		break;
13325f3847a4SMat Martineau 	}
13335f3847a4SMat Martineau }
13345f3847a4SMat Martineau 
13359f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
13369f0caeb1SVinicius Costa Gomes {
1337315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1338315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1339315917e0SJohan Hedberg 	 * procedure is complete.
1340315917e0SJohan Hedberg 	 */
1341315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1342315917e0SJohan Hedberg 		return;
1343315917e0SJohan Hedberg 
13442827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
13459f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
13469f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
13479f0caeb1SVinicius Costa Gomes 
134815f02b91SLuiz Augusto von Dentz 	switch (chan->mode) {
134915f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_LE_FLOWCTL:
135015f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
135115f02b91SLuiz Augusto von Dentz 		if (!chan->tx_credits)
13520ce43ce6SJohan Hedberg 			chan->ops->suspend(chan);
135315f02b91SLuiz Augusto von Dentz 		break;
135415f02b91SLuiz Augusto von Dentz 	}
1355177f8f2bSJohan Hedberg 
135654a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
13579f0caeb1SVinicius Costa Gomes 
135854a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
13599f0caeb1SVinicius Costa Gomes }
13609f0caeb1SVinicius Costa Gomes 
1361f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1362f1496deeSJohan Hedberg {
1363f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1364f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1365f1496deeSJohan Hedberg 
1366595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1367595177f3SJohan Hedberg 		return;
1368595177f3SJohan Hedberg 
13694b6e228eSLuiz Augusto von Dentz 	if (!chan->imtu)
13704b6e228eSLuiz Augusto von Dentz 		chan->imtu = chan->conn->mtu;
13714b6e228eSLuiz Augusto von Dentz 
1372ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1373fe149310SLuiz Augusto von Dentz 
1374f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1375f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1376f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
13773916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
13780cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1379f1496deeSJohan Hedberg 
1380f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1381f1496deeSJohan Hedberg 
1382f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1383f1496deeSJohan Hedberg 		       sizeof(req), &req);
1384f1496deeSJohan Hedberg }
1385f1496deeSJohan Hedberg 
1386da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
138715f02b91SLuiz Augusto von Dentz 	struct {
138815f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_req req;
1389da49b602SLuiz Augusto von Dentz 		__le16 scid[5];
139015f02b91SLuiz Augusto von Dentz 	} __packed pdu;
1391da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
1392da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1393da49b602SLuiz Augusto von Dentz 	int count;
1394da49b602SLuiz Augusto von Dentz };
1395da49b602SLuiz Augusto von Dentz 
1396da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1397da49b602SLuiz Augusto von Dentz {
1398da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data *conn = data;
1399da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1400da49b602SLuiz Augusto von Dentz 
1401da49b602SLuiz Augusto von Dentz 	if (chan == conn->chan)
1402da49b602SLuiz Augusto von Dentz 		return;
1403da49b602SLuiz Augusto von Dentz 
1404da49b602SLuiz Augusto von Dentz 	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1405da49b602SLuiz Augusto von Dentz 		return;
1406da49b602SLuiz Augusto von Dentz 
1407da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
1408da49b602SLuiz Augusto von Dentz 
1409da49b602SLuiz Augusto von Dentz 	/* Only add deferred channels with the same PID/PSM */
1410da49b602SLuiz Augusto von Dentz 	if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1411da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1412da49b602SLuiz Augusto von Dentz 		return;
141315f02b91SLuiz Augusto von Dentz 
141415f02b91SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
141515f02b91SLuiz Augusto von Dentz 		return;
141615f02b91SLuiz Augusto von Dentz 
141715f02b91SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
141815f02b91SLuiz Augusto von Dentz 
1419da49b602SLuiz Augusto von Dentz 	/* Set the same ident so we can match on the rsp */
1420da49b602SLuiz Augusto von Dentz 	chan->ident = conn->chan->ident;
1421da49b602SLuiz Augusto von Dentz 
1422da49b602SLuiz Augusto von Dentz 	/* Include all channels deferred */
1423da49b602SLuiz Augusto von Dentz 	conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1424da49b602SLuiz Augusto von Dentz 
1425da49b602SLuiz Augusto von Dentz 	conn->count++;
1426da49b602SLuiz Augusto von Dentz }
1427da49b602SLuiz Augusto von Dentz 
1428da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1429da49b602SLuiz Augusto von Dentz {
1430da49b602SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
1431da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data data;
1432da49b602SLuiz Augusto von Dentz 
1433da49b602SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1434da49b602SLuiz Augusto von Dentz 		return;
1435da49b602SLuiz Augusto von Dentz 
1436da49b602SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1437da49b602SLuiz Augusto von Dentz 		return;
1438da49b602SLuiz Augusto von Dentz 
1439da49b602SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
1440da49b602SLuiz Augusto von Dentz 
1441da49b602SLuiz Augusto von Dentz 	data.pdu.req.psm     = chan->psm;
1442da49b602SLuiz Augusto von Dentz 	data.pdu.req.mtu     = cpu_to_le16(chan->imtu);
1443da49b602SLuiz Augusto von Dentz 	data.pdu.req.mps     = cpu_to_le16(chan->mps);
1444da49b602SLuiz Augusto von Dentz 	data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1445da49b602SLuiz Augusto von Dentz 	data.pdu.scid[0]     = cpu_to_le16(chan->scid);
144615f02b91SLuiz Augusto von Dentz 
144715f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
1448da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1449da49b602SLuiz Augusto von Dentz 
1450da49b602SLuiz Augusto von Dentz 	data.count = 1;
1451da49b602SLuiz Augusto von Dentz 	data.chan = chan;
1452da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1453da49b602SLuiz Augusto von Dentz 
1454da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
145515f02b91SLuiz Augusto von Dentz 
145615f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1457da49b602SLuiz Augusto von Dentz 		       sizeof(data.pdu.req) + data.count * sizeof(__le16),
1458da49b602SLuiz Augusto von Dentz 		       &data.pdu);
145915f02b91SLuiz Augusto von Dentz }
146015f02b91SLuiz Augusto von Dentz 
1461f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1462f1496deeSJohan Hedberg {
1463f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1464f1496deeSJohan Hedberg 
1465f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1466f1496deeSJohan Hedberg 		return;
1467f1496deeSJohan Hedberg 
1468f1496deeSJohan Hedberg 	if (!chan->psm) {
1469f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1470f1496deeSJohan Hedberg 		return;
1471f1496deeSJohan Hedberg 	}
1472f1496deeSJohan Hedberg 
147315f02b91SLuiz Augusto von Dentz 	if (chan->state == BT_CONNECT) {
147415f02b91SLuiz Augusto von Dentz 		if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
147515f02b91SLuiz Augusto von Dentz 			l2cap_ecred_connect(chan);
147615f02b91SLuiz Augusto von Dentz 		else
1477f1496deeSJohan Hedberg 			l2cap_le_connect(chan);
1478f1496deeSJohan Hedberg 	}
147915f02b91SLuiz Augusto von Dentz }
1480f1496deeSJohan Hedberg 
148193c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
148293c3e8f5SAndrei Emeltchenko {
148393c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
148493c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
148593c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1486f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1487f1496deeSJohan Hedberg 		l2cap_le_start(chan);
148893c3e8f5SAndrei Emeltchenko 	} else {
148993c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
149093c3e8f5SAndrei Emeltchenko 	}
149193c3e8f5SAndrei Emeltchenko }
149293c3e8f5SAndrei Emeltchenko 
1493aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
14940a708f8fSGustavo F. Padovan {
14950a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1496aeaeb4bbSJohan Hedberg 
1497aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1498aeaeb4bbSJohan Hedberg 		return;
1499aeaeb4bbSJohan Hedberg 
1500dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
15010a708f8fSGustavo F. Padovan 
15020a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
15030a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
15040a708f8fSGustavo F. Padovan 
1505ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
15060a708f8fSGustavo F. Padovan 
15072d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
15082d792818SGustavo Padovan 		       sizeof(req), &req);
15090a708f8fSGustavo F. Padovan }
1510aeaeb4bbSJohan Hedberg 
1511693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1512693cd8ceSMarcel Holtmann {
1513693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1514693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1515693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1516693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1517693cd8ceSMarcel Holtmann 	 *
1518693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1519693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1520693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1521693cd8ceSMarcel Holtmann 	 */
1522288c0697SArchie Pusaka 	int min_key_size = hcon->hdev->min_enc_key_size;
1523288c0697SArchie Pusaka 
1524288c0697SArchie Pusaka 	/* On FIPS security level, key size must be 16 bytes */
1525288c0697SArchie Pusaka 	if (hcon->sec_level == BT_SECURITY_FIPS)
1526288c0697SArchie Pusaka 		min_key_size = 16;
1527288c0697SArchie Pusaka 
1528693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1529288c0697SArchie Pusaka 		hcon->enc_key_size >= min_key_size);
1530693cd8ceSMarcel Holtmann }
1531693cd8ceSMarcel Holtmann 
1532aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1533aeaeb4bbSJohan Hedberg {
1534aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1535aeaeb4bbSJohan Hedberg 
1536aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1537aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1538aeaeb4bbSJohan Hedberg 		return;
1539aeaeb4bbSJohan Hedberg 	}
1540aeaeb4bbSJohan Hedberg 
1541aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1542aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1543aeaeb4bbSJohan Hedberg 		return;
1544aeaeb4bbSJohan Hedberg 	}
1545aeaeb4bbSJohan Hedberg 
1546aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1547aeaeb4bbSJohan Hedberg 		return;
1548aeaeb4bbSJohan Hedberg 
1549693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1550693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1551693cd8ceSMarcel Holtmann 		return;
1552693cd8ceSMarcel Holtmann 
1553693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1554aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1555693cd8ceSMarcel Holtmann 	else
1556693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
15570a708f8fSGustavo F. Padovan }
15580a708f8fSGustavo F. Padovan 
15590a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
15600a708f8fSGustavo F. Padovan {
15610a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
15620a708f8fSGustavo F. Padovan 	if (!disable_ertm)
15630a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
15640a708f8fSGustavo F. Padovan 
15650a708f8fSGustavo F. Padovan 	switch (mode) {
15660a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
15670a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
15680a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
15690a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
15700a708f8fSGustavo F. Padovan 	default:
15710a708f8fSGustavo F. Padovan 		return 0x00;
15720a708f8fSGustavo F. Padovan 	}
15730a708f8fSGustavo F. Padovan }
15740a708f8fSGustavo F. Padovan 
15755e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
15760a708f8fSGustavo F. Padovan {
15775e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
15780a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
15790a708f8fSGustavo F. Padovan 
15800a708f8fSGustavo F. Padovan 	if (!conn)
15810a708f8fSGustavo F. Padovan 		return;
15820a708f8fSGustavo F. Padovan 
1583aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
15841a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
15851a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
15861a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
15870a708f8fSGustavo F. Padovan 	}
15880a708f8fSGustavo F. Padovan 
15892338a7e0SJohan Hedberg 	if (chan->scid == L2CAP_CID_A2MP) {
1590d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1591416fa752SAndrei Emeltchenko 		return;
1592416fa752SAndrei Emeltchenko 	}
1593416fa752SAndrei Emeltchenko 
1594fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1595fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
15962d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
15972d792818SGustavo Padovan 		       sizeof(req), &req);
15980a708f8fSGustavo F. Padovan 
1599f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
16000a708f8fSGustavo F. Padovan }
16010a708f8fSGustavo F. Padovan 
16020a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
16030a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
16040a708f8fSGustavo F. Padovan {
16053df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
16060a708f8fSGustavo F. Padovan 
16070a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
16080a708f8fSGustavo F. Padovan 
16093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16100a708f8fSGustavo F. Padovan 
16113df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
16126be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16130a708f8fSGustavo F. Padovan 
1614715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1615aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
16166be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
16170a708f8fSGustavo F. Padovan 			continue;
16180a708f8fSGustavo F. Padovan 		}
16190a708f8fSGustavo F. Padovan 
162089bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1621e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1622b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
16236be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16240a708f8fSGustavo F. Padovan 				continue;
16250a708f8fSGustavo F. Padovan 			}
16260a708f8fSGustavo F. Padovan 
1627c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1628c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1629c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
16300f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
16316be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16320a708f8fSGustavo F. Padovan 				continue;
16330a708f8fSGustavo F. Padovan 			}
16340a708f8fSGustavo F. Padovan 
1635693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
163693c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1637693cd8ceSMarcel Holtmann 			else
1638693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
16390a708f8fSGustavo F. Padovan 
164089bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
16410a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
16420a708f8fSGustavo F. Padovan 			char buf[128];
1643fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1644fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
16450a708f8fSGustavo F. Padovan 
1646e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1647bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1648dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1649dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
16502dc4e510SGustavo Padovan 					chan->ops->defer(chan);
16510a708f8fSGustavo F. Padovan 
16520a708f8fSGustavo F. Padovan 				} else {
1653acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1654dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1655dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
16560a708f8fSGustavo F. Padovan 				}
16570a708f8fSGustavo F. Padovan 			} else {
1658dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1659dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
16600a708f8fSGustavo F. Padovan 			}
16610a708f8fSGustavo F. Padovan 
1662fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1663fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
16640a708f8fSGustavo F. Padovan 
1665c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
16660a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
16676be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16680a708f8fSGustavo F. Padovan 				continue;
16690a708f8fSGustavo F. Padovan 			}
16700a708f8fSGustavo F. Padovan 
1671c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
16720a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1673e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
167473ffa904SGustavo F. Padovan 			chan->num_conf_req++;
16750a708f8fSGustavo F. Padovan 		}
16760a708f8fSGustavo F. Padovan 
16776be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
16780a708f8fSGustavo F. Padovan 	}
16790a708f8fSGustavo F. Padovan 
16803df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
16810a708f8fSGustavo F. Padovan }
16820a708f8fSGustavo F. Padovan 
1683b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1684b62f328bSVille Tervo {
1685cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1686dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1687b62f328bSVille Tervo 
1688e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1689b62f328bSVille Tervo 
1690e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1691e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1692e760ec12SJohan Hedberg 	 */
1693e760ec12SJohan Hedberg 	if (hcon->out)
1694e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1695cc8dba2bSMarcel Holtmann 
169680afeb6cSMarcel Holtmann 	/* For LE slave connections, make sure the connection interval
169780afeb6cSMarcel Holtmann 	 * is in the range of the minium and maximum interval that has
169880afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
169980afeb6cSMarcel Holtmann 	 * the connection update procedure.
170080afeb6cSMarcel Holtmann 	 */
170140bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
170280afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
170380afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
170480afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
170580afeb6cSMarcel Holtmann 
170680afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
170780afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
170880afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
170980afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
171080afeb6cSMarcel Holtmann 
171180afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
171280afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
171380afeb6cSMarcel Holtmann 	}
1714b62f328bSVille Tervo }
1715b62f328bSVille Tervo 
17160a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
17170a708f8fSGustavo F. Padovan {
171848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1719cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
17200a708f8fSGustavo F. Padovan 
17210a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17220a708f8fSGustavo F. Padovan 
1723aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1724aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1725aeaeb4bbSJohan Hedberg 
1726e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1727e760ec12SJohan Hedberg 
17283df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1729baa7e1faSGustavo F. Padovan 
17306be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17310a708f8fSGustavo F. Padovan 
17322338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
1733416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1734416fa752SAndrei Emeltchenko 			continue;
1735416fa752SAndrei Emeltchenko 		}
1736416fa752SAndrei Emeltchenko 
1737cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1738f1496deeSJohan Hedberg 			l2cap_le_start(chan);
173963128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1740aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
174174e75740SGustavo Padovan 				l2cap_chan_ready(chan);
17421c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1743fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
17441c244f79SGustavo Padovan 		}
17450a708f8fSGustavo F. Padovan 
17466be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17470a708f8fSGustavo F. Padovan 	}
17480a708f8fSGustavo F. Padovan 
17493df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
175061a939c6SJohan Hedberg 
175179a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
175279a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
175379a05727SJohan Hedberg 
175461a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
17550a708f8fSGustavo F. Padovan }
17560a708f8fSGustavo F. Padovan 
17570a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
17580a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
17590a708f8fSGustavo F. Padovan {
176048454079SGustavo F. Padovan 	struct l2cap_chan *chan;
17610a708f8fSGustavo F. Padovan 
17620a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17630a708f8fSGustavo F. Padovan 
17643df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17650a708f8fSGustavo F. Padovan 
17663df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1767ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
17681d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
17690a708f8fSGustavo F. Padovan 	}
17700a708f8fSGustavo F. Padovan 
17713df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17720a708f8fSGustavo F. Padovan }
17730a708f8fSGustavo F. Padovan 
1774f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
17750a708f8fSGustavo F. Padovan {
1776f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1777030013d8SGustavo F. Padovan 					       info_timer.work);
17780a708f8fSGustavo F. Padovan 
17790a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
17800a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
17810a708f8fSGustavo F. Padovan 
17820a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
17830a708f8fSGustavo F. Padovan }
17840a708f8fSGustavo F. Padovan 
17852c8e1411SDavid Herrmann /*
17862c8e1411SDavid Herrmann  * l2cap_user
17872c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
17882c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
17892c8e1411SDavid Herrmann  * during unregistration.
17902c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
17912c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
17922c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
17932c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
17942c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
17952c8e1411SDavid Herrmann  * any time if they don't.
17962c8e1411SDavid Herrmann  */
17972c8e1411SDavid Herrmann 
17982c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
17992c8e1411SDavid Herrmann {
18002c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
18012c8e1411SDavid Herrmann 	int ret;
18022c8e1411SDavid Herrmann 
18032c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
18042c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
18052c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
18062c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
18072c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
18082c8e1411SDavid Herrmann 	 * here, too. */
18092c8e1411SDavid Herrmann 
18102c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18112c8e1411SDavid Herrmann 
1812835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
18132c8e1411SDavid Herrmann 		ret = -EINVAL;
18142c8e1411SDavid Herrmann 		goto out_unlock;
18152c8e1411SDavid Herrmann 	}
18162c8e1411SDavid Herrmann 
18172c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
18182c8e1411SDavid Herrmann 	if (!conn->hchan) {
18192c8e1411SDavid Herrmann 		ret = -ENODEV;
18202c8e1411SDavid Herrmann 		goto out_unlock;
18212c8e1411SDavid Herrmann 	}
18222c8e1411SDavid Herrmann 
18232c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
18242c8e1411SDavid Herrmann 	if (ret)
18252c8e1411SDavid Herrmann 		goto out_unlock;
18262c8e1411SDavid Herrmann 
18272c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
18282c8e1411SDavid Herrmann 	ret = 0;
18292c8e1411SDavid Herrmann 
18302c8e1411SDavid Herrmann out_unlock:
18312c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18322c8e1411SDavid Herrmann 	return ret;
18332c8e1411SDavid Herrmann }
18342c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
18352c8e1411SDavid Herrmann 
18362c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
18372c8e1411SDavid Herrmann {
18382c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
18392c8e1411SDavid Herrmann 
18402c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18412c8e1411SDavid Herrmann 
1842835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
18432c8e1411SDavid Herrmann 		goto out_unlock;
18442c8e1411SDavid Herrmann 
1845ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
18462c8e1411SDavid Herrmann 	user->remove(conn, user);
18472c8e1411SDavid Herrmann 
18482c8e1411SDavid Herrmann out_unlock:
18492c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18502c8e1411SDavid Herrmann }
18512c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
18522c8e1411SDavid Herrmann 
18532c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
18542c8e1411SDavid Herrmann {
18552c8e1411SDavid Herrmann 	struct l2cap_user *user;
18562c8e1411SDavid Herrmann 
18572c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
18582c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1859ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
18602c8e1411SDavid Herrmann 		user->remove(conn, user);
18612c8e1411SDavid Herrmann 	}
18622c8e1411SDavid Herrmann }
18632c8e1411SDavid Herrmann 
18645d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
18655d3de7dfSVinicius Costa Gomes {
18665d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
18675d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
18685d3de7dfSVinicius Costa Gomes 
18695d3de7dfSVinicius Costa Gomes 	if (!conn)
18705d3de7dfSVinicius Costa Gomes 		return;
18715d3de7dfSVinicius Costa Gomes 
18725d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
18735d3de7dfSVinicius Costa Gomes 
18745d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
18755d3de7dfSVinicius Costa Gomes 
187661a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
18777ab56c3aSJukka Taimisto 
18787ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
18797ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
18807ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
18817ab56c3aSJukka Taimisto 	 */
18827ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
18837ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
188461a939c6SJohan Hedberg 
1885f3d82d0cSJohan Hedberg 	if (work_pending(&conn->id_addr_update_work))
1886f3d82d0cSJohan Hedberg 		cancel_work_sync(&conn->id_addr_update_work);
1887f3d82d0cSJohan Hedberg 
18882c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
18892c8e1411SDavid Herrmann 
1890e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1891e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1892e31fb860SJohan Hedberg 
18933df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
18943df91ea2SAndrei Emeltchenko 
18955d3de7dfSVinicius Costa Gomes 	/* Kill channels */
18965d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
189761d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
18986be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
18996be36555SAndrei Emeltchenko 
19005d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
19016be36555SAndrei Emeltchenko 
190280b98027SGustavo Padovan 		chan->ops->close(chan);
19036c08fc89SManish Mandlik 
19046c08fc89SManish Mandlik 		l2cap_chan_unlock(chan);
190561d6ef3eSMat Martineau 		l2cap_chan_put(chan);
19065d3de7dfSVinicius Costa Gomes 	}
19075d3de7dfSVinicius Costa Gomes 
19083df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
19093df91ea2SAndrei Emeltchenko 
191073d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
191173d80debSLuiz Augusto von Dentz 
19125d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1913127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
19145d3de7dfSVinicius Costa Gomes 
19155d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
19169c903e37SDavid Herrmann 	conn->hchan = NULL;
19179c903e37SDavid Herrmann 	l2cap_conn_put(conn);
19185d3de7dfSVinicius Costa Gomes }
19195d3de7dfSVinicius Costa Gomes 
19209c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
19219c903e37SDavid Herrmann {
19229c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
19239c903e37SDavid Herrmann 
19249c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
19259c903e37SDavid Herrmann 	kfree(conn);
19269c903e37SDavid Herrmann }
19279c903e37SDavid Herrmann 
192851bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
19299c903e37SDavid Herrmann {
19309c903e37SDavid Herrmann 	kref_get(&conn->ref);
193151bb8457SJohan Hedberg 	return conn;
19329c903e37SDavid Herrmann }
19339c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
19349c903e37SDavid Herrmann 
19359c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
19369c903e37SDavid Herrmann {
19379c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
19389c903e37SDavid Herrmann }
19399c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
19409c903e37SDavid Herrmann 
19410a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
19420a708f8fSGustavo F. Padovan 
1943c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
19440a708f8fSGustavo F. Padovan  * Returns closest match.
19450a708f8fSGustavo F. Padovan  */
1946c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1947c2287681SIdo Yariv 						   bdaddr_t *src,
1948bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1949bf20fd4eSJohan Hedberg 						   u8 link_type)
19500a708f8fSGustavo F. Padovan {
195123691d75SGustavo F. Padovan 	struct l2cap_chan *c, *c1 = NULL;
19520a708f8fSGustavo F. Padovan 
195323691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
19540a708f8fSGustavo F. Padovan 
195523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
195689bc500eSGustavo F. Padovan 		if (state && c->state != state)
19570a708f8fSGustavo F. Padovan 			continue;
19580a708f8fSGustavo F. Padovan 
1959bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1960bf20fd4eSJohan Hedberg 			continue;
1961bf20fd4eSJohan Hedberg 
1962bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1963bf20fd4eSJohan Hedberg 			continue;
1964bf20fd4eSJohan Hedberg 
196523691d75SGustavo F. Padovan 		if (c->psm == psm) {
1966c2287681SIdo Yariv 			int src_match, dst_match;
1967c2287681SIdo Yariv 			int src_any, dst_any;
1968c2287681SIdo Yariv 
19690a708f8fSGustavo F. Padovan 			/* Exact match. */
19707eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
19717eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1972c2287681SIdo Yariv 			if (src_match && dst_match) {
1973a24cce14SJohan Hedberg 				l2cap_chan_hold(c);
1974a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
197523691d75SGustavo F. Padovan 				return c;
197623691d75SGustavo F. Padovan 			}
19770a708f8fSGustavo F. Padovan 
19780a708f8fSGustavo F. Padovan 			/* Closest match */
19797eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
19807eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
1981c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
1982c2287681SIdo Yariv 			    (src_any && dst_any))
198323691d75SGustavo F. Padovan 				c1 = c;
19840a708f8fSGustavo F. Padovan 		}
19850a708f8fSGustavo F. Padovan 	}
19860a708f8fSGustavo F. Padovan 
1987a24cce14SJohan Hedberg 	if (c1)
1988a24cce14SJohan Hedberg 		l2cap_chan_hold(c1);
1989a24cce14SJohan Hedberg 
199023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
19910a708f8fSGustavo F. Padovan 
199223691d75SGustavo F. Padovan 	return c1;
19930a708f8fSGustavo F. Padovan }
19940a708f8fSGustavo F. Padovan 
1995721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
19960a708f8fSGustavo F. Padovan {
1997721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
1998721c4181SGustavo F. Padovan 					       monitor_timer.work);
19990a708f8fSGustavo F. Padovan 
2000525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
20010a708f8fSGustavo F. Padovan 
20026be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20036be36555SAndrei Emeltchenko 
200480909e04SMat Martineau 	if (!chan->conn) {
20056be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
20068d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
20070a708f8fSGustavo F. Padovan 		return;
20080a708f8fSGustavo F. Padovan 	}
20090a708f8fSGustavo F. Padovan 
2010401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
20110a708f8fSGustavo F. Padovan 
20126be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20138d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20140a708f8fSGustavo F. Padovan }
20150a708f8fSGustavo F. Padovan 
2016721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20170a708f8fSGustavo F. Padovan {
2018721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2019721c4181SGustavo F. Padovan 					       retrans_timer.work);
20200a708f8fSGustavo F. Padovan 
202149208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20220a708f8fSGustavo F. Padovan 
20236be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20246be36555SAndrei Emeltchenko 
202580909e04SMat Martineau 	if (!chan->conn) {
202680909e04SMat Martineau 		l2cap_chan_unlock(chan);
202780909e04SMat Martineau 		l2cap_chan_put(chan);
202880909e04SMat Martineau 		return;
202980909e04SMat Martineau 	}
20300a708f8fSGustavo F. Padovan 
2031401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20326be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20338d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20340a708f8fSGustavo F. Padovan }
20350a708f8fSGustavo F. Padovan 
2036d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20373733937dSMat Martineau 				 struct sk_buff_head *skbs)
20380a708f8fSGustavo F. Padovan {
20390a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20403733937dSMat Martineau 	struct l2cap_ctrl *control;
20410a708f8fSGustavo F. Padovan 
20423733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20433733937dSMat Martineau 
2044b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2045b99e13adSMat Martineau 		return;
2046b99e13adSMat Martineau 
20473733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20483733937dSMat Martineau 
20493733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20503733937dSMat Martineau 
20513733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20523733937dSMat Martineau 
2053a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2054a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
20553733937dSMat Martineau 
20563733937dSMat Martineau 		control->reqseq = 0;
20573733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20583733937dSMat Martineau 
20593733937dSMat Martineau 		__pack_control(chan, control, skb);
20600a708f8fSGustavo F. Padovan 
206147d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20623733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20633733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20640a708f8fSGustavo F. Padovan 		}
20650a708f8fSGustavo F. Padovan 
20664343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20670a708f8fSGustavo F. Padovan 
2068b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20693733937dSMat Martineau 
2070836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20713733937dSMat Martineau 		chan->frames_sent++;
20720a708f8fSGustavo F. Padovan 	}
20730a708f8fSGustavo F. Padovan }
20740a708f8fSGustavo F. Padovan 
207567c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
20760a708f8fSGustavo F. Padovan {
20770a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
207818a48e76SMat Martineau 	struct l2cap_ctrl *control;
207918a48e76SMat Martineau 	int sent = 0;
208018a48e76SMat Martineau 
208118a48e76SMat Martineau 	BT_DBG("chan %p", chan);
20820a708f8fSGustavo F. Padovan 
208389bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
20840a708f8fSGustavo F. Padovan 		return -ENOTCONN;
20850a708f8fSGustavo F. Padovan 
208694122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
208794122bbeSMat Martineau 		return 0;
208894122bbeSMat Martineau 
2089b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2090b99e13adSMat Martineau 		return 0;
2091b99e13adSMat Martineau 
209218a48e76SMat Martineau 	while (chan->tx_send_head &&
209318a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
209418a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
20950a708f8fSGustavo F. Padovan 
209618a48e76SMat Martineau 		skb = chan->tx_send_head;
20970a708f8fSGustavo F. Padovan 
2098a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2099a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
21000a708f8fSGustavo F. Padovan 
2101e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
210218a48e76SMat Martineau 			control->final = 1;
2103e2ab4353SGustavo F. Padovan 
210418a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
210518a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
210618a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
21070a708f8fSGustavo F. Padovan 
210818a48e76SMat Martineau 		__pack_control(chan, control, skb);
21090a708f8fSGustavo F. Padovan 
211047d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
211118a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
211218a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
21130a708f8fSGustavo F. Padovan 		}
21140a708f8fSGustavo F. Padovan 
211518a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
211618a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
211718a48e76SMat Martineau 		 */
211818a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
211918a48e76SMat Martineau 
212018a48e76SMat Martineau 		if (!tx_skb)
212118a48e76SMat Martineau 			break;
21220a708f8fSGustavo F. Padovan 
21231a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21240a708f8fSGustavo F. Padovan 
2125836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21266a026610SGustavo F. Padovan 		chan->unacked_frames++;
21276a026610SGustavo F. Padovan 		chan->frames_sent++;
212818a48e76SMat Martineau 		sent++;
21290a708f8fSGustavo F. Padovan 
213058d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
213158d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21320a708f8fSGustavo F. Padovan 		else
213358d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
213418a48e76SMat Martineau 
213518a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2136b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21370a708f8fSGustavo F. Padovan 	}
21380a708f8fSGustavo F. Padovan 
2139b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2140b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
214118a48e76SMat Martineau 
214218a48e76SMat Martineau 	return sent;
21430a708f8fSGustavo F. Padovan }
21440a708f8fSGustavo F. Padovan 
2145e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2146e1fbd4c1SMat Martineau {
2147e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2148e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2149e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2150e1fbd4c1SMat Martineau 	u16 seq;
2151e1fbd4c1SMat Martineau 
2152e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2153e1fbd4c1SMat Martineau 
2154e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2155e1fbd4c1SMat Martineau 		return;
2156e1fbd4c1SMat Martineau 
2157b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2158b99e13adSMat Martineau 		return;
2159b99e13adSMat Martineau 
2160e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2161e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2162e1fbd4c1SMat Martineau 
2163e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2164e1fbd4c1SMat Martineau 		if (!skb) {
2165e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2166e1fbd4c1SMat Martineau 			       seq);
2167e1fbd4c1SMat Martineau 			continue;
2168e1fbd4c1SMat Martineau 		}
2169e1fbd4c1SMat Martineau 
2170a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
2171a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
2172e1fbd4c1SMat Martineau 
2173e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2174a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2175e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
21765e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2177e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2178e1fbd4c1SMat Martineau 			break;
2179e1fbd4c1SMat Martineau 		}
2180e1fbd4c1SMat Martineau 
2181e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2182e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2183e1fbd4c1SMat Martineau 			control.final = 1;
2184e1fbd4c1SMat Martineau 		else
2185e1fbd4c1SMat Martineau 			control.final = 0;
2186e1fbd4c1SMat Martineau 
2187e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2188e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2189e1fbd4c1SMat Martineau 			 * writeable copy
2190e1fbd4c1SMat Martineau 			 */
21918bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2192e1fbd4c1SMat Martineau 		} else {
21938bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2194e1fbd4c1SMat Martineau 		}
2195e1fbd4c1SMat Martineau 
2196e1fbd4c1SMat Martineau 		if (!tx_skb) {
2197e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2198e1fbd4c1SMat Martineau 			break;
2199e1fbd4c1SMat Martineau 		}
2200e1fbd4c1SMat Martineau 
2201e1fbd4c1SMat Martineau 		/* Update skb contents */
2202e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2203e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2204e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2205e1fbd4c1SMat Martineau 		} else {
2206e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2207e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2208e1fbd4c1SMat Martineau 		}
2209e1fbd4c1SMat Martineau 
221013cac152SLukasz Rymanowski 		/* Update FCS */
2211e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
221213cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
221313cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
221413cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
221513cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2216e1fbd4c1SMat Martineau 		}
2217e1fbd4c1SMat Martineau 
2218e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2219e1fbd4c1SMat Martineau 
2220e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2221e1fbd4c1SMat Martineau 
2222e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2223e1fbd4c1SMat Martineau 	}
2224e1fbd4c1SMat Martineau }
2225e1fbd4c1SMat Martineau 
2226f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2227f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2228f80842a8SMat Martineau {
2229f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2230f80842a8SMat Martineau 
2231f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2232f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2233f80842a8SMat Martineau }
2234f80842a8SMat Martineau 
2235d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2236d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2237d2a7ac5dSMat Martineau {
2238e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2239e1fbd4c1SMat Martineau 
2240e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2241e1fbd4c1SMat Martineau 
2242e1fbd4c1SMat Martineau 	if (control->poll)
2243e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2244e1fbd4c1SMat Martineau 
2245e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2246e1fbd4c1SMat Martineau 
2247e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2248e1fbd4c1SMat Martineau 		return;
2249e1fbd4c1SMat Martineau 
2250e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2251e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2252a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2253e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2254e1fbd4c1SMat Martineau 				break;
2255e1fbd4c1SMat Martineau 		}
2256e1fbd4c1SMat Martineau 
2257e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2258e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2259e1fbd4c1SMat Martineau 				break;
2260e1fbd4c1SMat Martineau 
2261e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2262a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2263e1fbd4c1SMat Martineau 		}
2264e1fbd4c1SMat Martineau 
2265e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2266e1fbd4c1SMat Martineau 	}
2267d2a7ac5dSMat Martineau }
2268d2a7ac5dSMat Martineau 
2269b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2270b17e73bbSSzymon Janc {
22710a0aba42SMat Martineau 	struct l2cap_ctrl control;
22720a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
22730a0aba42SMat Martineau 					 chan->last_acked_seq);
22740a0aba42SMat Martineau 	int threshold;
22750a0aba42SMat Martineau 
22760a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
22770a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
22780a0aba42SMat Martineau 
22790a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
22800a0aba42SMat Martineau 	control.sframe = 1;
22810a0aba42SMat Martineau 
22820a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
22830a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2284b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
22850a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
22860a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
22870a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
22880a0aba42SMat Martineau 	} else {
22890a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
22900a0aba42SMat Martineau 			l2cap_ertm_send(chan);
22910a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
22920a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
22930a0aba42SMat Martineau 				frames_to_ack = 0;
22940a0aba42SMat Martineau 		}
22950a0aba42SMat Martineau 
2296c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
22970a0aba42SMat Martineau 		 * Calculate without mul or div
22980a0aba42SMat Martineau 		 */
2299c20f8e35SMat Martineau 		threshold = chan->ack_win;
23000a0aba42SMat Martineau 		threshold += threshold << 1;
23010a0aba42SMat Martineau 		threshold >>= 2;
23020a0aba42SMat Martineau 
2303b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
23040a0aba42SMat Martineau 		       threshold);
23050a0aba42SMat Martineau 
23060a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
23070a0aba42SMat Martineau 			__clear_ack_timer(chan);
23080a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
23090a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
23100a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
23110a0aba42SMat Martineau 			frames_to_ack = 0;
23120a0aba42SMat Martineau 		}
23130a0aba42SMat Martineau 
23140a0aba42SMat Martineau 		if (frames_to_ack)
23150a0aba42SMat Martineau 			__set_ack_timer(chan);
23160a0aba42SMat Martineau 	}
2317b17e73bbSSzymon Janc }
2318b17e73bbSSzymon Janc 
231904124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
232004124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
232104124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23220a708f8fSGustavo F. Padovan {
23230952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23240a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
232590338947SGustavo Padovan 	int sent = 0;
23260a708f8fSGustavo F. Padovan 
2327cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
23280a708f8fSGustavo F. Padovan 		return -EFAULT;
23290a708f8fSGustavo F. Padovan 
23300a708f8fSGustavo F. Padovan 	sent += count;
23310a708f8fSGustavo F. Padovan 	len  -= count;
23320a708f8fSGustavo F. Padovan 
23330a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23340a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23350a708f8fSGustavo F. Padovan 	while (len) {
2336fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2337fbe00700SGustavo Padovan 
23380a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23390a708f8fSGustavo F. Padovan 
2340d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
234190338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2342fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2343fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23442f7719ceSAndrei Emeltchenko 
2345fbe00700SGustavo Padovan 		*frag = tmp;
2346fbe00700SGustavo Padovan 
2347cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2348cbbd26b8SAl Viro 				   &msg->msg_iter))
23490a708f8fSGustavo F. Padovan 			return -EFAULT;
23500a708f8fSGustavo F. Padovan 
23510a708f8fSGustavo F. Padovan 		sent += count;
23520a708f8fSGustavo F. Padovan 		len  -= count;
23530a708f8fSGustavo F. Padovan 
23542d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23552d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23562d0ed3d5SGustavo Padovan 
23570a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23580a708f8fSGustavo F. Padovan 	}
23590a708f8fSGustavo F. Padovan 
23600a708f8fSGustavo F. Padovan 	return sent;
23610a708f8fSGustavo F. Padovan }
23620a708f8fSGustavo F. Padovan 
23635e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23648d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
23650a708f8fSGustavo F. Padovan {
23668c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23670a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
236803a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23690a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23700a708f8fSGustavo F. Padovan 
23718d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
23728d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
23730a708f8fSGustavo F. Padovan 
23740a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
23752f7719ceSAndrei Emeltchenko 
2376d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
237790338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
237890338947SGustavo Padovan 	if (IS_ERR(skb))
237990338947SGustavo Padovan 		return skb;
23800a708f8fSGustavo F. Padovan 
23810a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
23824df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2383fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2384daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
238543b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
23860a708f8fSGustavo F. Padovan 
23870952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
23880a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
23890a708f8fSGustavo F. Padovan 		kfree_skb(skb);
23900a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
23910a708f8fSGustavo F. Padovan 	}
23920a708f8fSGustavo F. Padovan 	return skb;
23930a708f8fSGustavo F. Padovan }
23940a708f8fSGustavo F. Padovan 
23955e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
23968d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
23970a708f8fSGustavo F. Padovan {
23988c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23990a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2400f2ba7faeSGustavo Padovan 	int err, count;
24010a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24020a708f8fSGustavo F. Padovan 
2403b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24040a708f8fSGustavo F. Padovan 
2405f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
24062f7719ceSAndrei Emeltchenko 
2407d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
240890338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
240990338947SGustavo Padovan 	if (IS_ERR(skb))
241090338947SGustavo Padovan 		return skb;
24110a708f8fSGustavo F. Padovan 
24120a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24134df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2414fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24156ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24160a708f8fSGustavo F. Padovan 
24170952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24180a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24190a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24200a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24210a708f8fSGustavo F. Padovan 	}
24220a708f8fSGustavo F. Padovan 	return skb;
24230a708f8fSGustavo F. Padovan }
24240a708f8fSGustavo F. Padovan 
2425ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2426ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
242794122bbeSMat Martineau 					       u16 sdulen)
24280a708f8fSGustavo F. Padovan {
24298c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24300a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2431e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24320a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24330a708f8fSGustavo F. Padovan 
2434b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24350a708f8fSGustavo F. Padovan 
24360a708f8fSGustavo F. Padovan 	if (!conn)
24370a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24380a708f8fSGustavo F. Padovan 
2439ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2440e4ca6d98SAndrei Emeltchenko 
24410a708f8fSGustavo F. Padovan 	if (sdulen)
244203a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24430a708f8fSGustavo F. Padovan 
244447d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
244503a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24460a708f8fSGustavo F. Padovan 
24470a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24482f7719ceSAndrei Emeltchenko 
2449d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
245090338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
245190338947SGustavo Padovan 	if (IS_ERR(skb))
245290338947SGustavo Padovan 		return skb;
24530a708f8fSGustavo F. Padovan 
24540a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24554df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2456fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24570a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
245888843ab0SAndrei Emeltchenko 
245918a48e76SMat Martineau 	/* Control header is populated later */
246018a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
246118a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
246218a48e76SMat Martineau 	else
246318a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
246488843ab0SAndrei Emeltchenko 
24650a708f8fSGustavo F. Padovan 	if (sdulen)
246603a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24670a708f8fSGustavo F. Padovan 
24680952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24690a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24700a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24710a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24720a708f8fSGustavo F. Padovan 	}
24730a708f8fSGustavo F. Padovan 
2474a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2475a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
24760a708f8fSGustavo F. Padovan 	return skb;
24770a708f8fSGustavo F. Padovan }
24780a708f8fSGustavo F. Padovan 
247994122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
248094122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
248194122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
24820a708f8fSGustavo F. Padovan {
24830a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
248494122bbeSMat Martineau 	u16 sdu_len;
248594122bbeSMat Martineau 	size_t pdu_len;
248694122bbeSMat Martineau 	u8 sar;
24870a708f8fSGustavo F. Padovan 
2488b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
24890a708f8fSGustavo F. Padovan 
249094122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
249194122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
249294122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
249394122bbeSMat Martineau 	 */
249494122bbeSMat Martineau 
249594122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
249694122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
249794122bbeSMat Martineau 
2498a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2499a549574dSMat Martineau 	if (!chan->hs_hcon)
250094122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
250194122bbeSMat Martineau 
250294122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
250335d401dfSGustavo Padovan 	if (chan->fcs)
250435d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
250535d401dfSGustavo Padovan 
2506ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
250794122bbeSMat Martineau 
250894122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
250994122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
251094122bbeSMat Martineau 
251194122bbeSMat Martineau 	if (len <= pdu_len) {
251294122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
251394122bbeSMat Martineau 		sdu_len = 0;
251494122bbeSMat Martineau 		pdu_len = len;
251594122bbeSMat Martineau 	} else {
251694122bbeSMat Martineau 		sar = L2CAP_SAR_START;
251794122bbeSMat Martineau 		sdu_len = len;
251894122bbeSMat Martineau 	}
25190a708f8fSGustavo F. Padovan 
25200a708f8fSGustavo F. Padovan 	while (len > 0) {
252194122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25220a708f8fSGustavo F. Padovan 
25230a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
252494122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25250a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25260a708f8fSGustavo F. Padovan 		}
25270a708f8fSGustavo F. Padovan 
2528a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
252994122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25300a708f8fSGustavo F. Padovan 
253194122bbeSMat Martineau 		len -= pdu_len;
2532069cb270SLukasz Rymanowski 		if (sdu_len)
253394122bbeSMat Martineau 			sdu_len = 0;
253494122bbeSMat Martineau 
253594122bbeSMat Martineau 		if (len <= pdu_len) {
253694122bbeSMat Martineau 			sar = L2CAP_SAR_END;
253794122bbeSMat Martineau 			pdu_len = len;
253894122bbeSMat Martineau 		} else {
253994122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
254094122bbeSMat Martineau 		}
254194122bbeSMat Martineau 	}
254294122bbeSMat Martineau 
2543f0f62799SGustavo Padovan 	return 0;
25440a708f8fSGustavo F. Padovan }
25450a708f8fSGustavo F. Padovan 
2546177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2547177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2548177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2549177f8f2bSJohan Hedberg {
2550177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2551177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2552177f8f2bSJohan Hedberg 	int err, count, hlen;
2553177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2554177f8f2bSJohan Hedberg 
2555177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2556177f8f2bSJohan Hedberg 
2557177f8f2bSJohan Hedberg 	if (!conn)
2558177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2559177f8f2bSJohan Hedberg 
2560177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2561177f8f2bSJohan Hedberg 
2562177f8f2bSJohan Hedberg 	if (sdulen)
2563177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2564177f8f2bSJohan Hedberg 
2565177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2566177f8f2bSJohan Hedberg 
2567d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2568177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2569177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2570177f8f2bSJohan Hedberg 		return skb;
2571177f8f2bSJohan Hedberg 
2572177f8f2bSJohan Hedberg 	/* Create L2CAP header */
25734df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2574177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2575177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2576177f8f2bSJohan Hedberg 
2577177f8f2bSJohan Hedberg 	if (sdulen)
2578177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2579177f8f2bSJohan Hedberg 
2580177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2581177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2582177f8f2bSJohan Hedberg 		kfree_skb(skb);
2583177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2584177f8f2bSJohan Hedberg 	}
2585177f8f2bSJohan Hedberg 
2586177f8f2bSJohan Hedberg 	return skb;
2587177f8f2bSJohan Hedberg }
2588177f8f2bSJohan Hedberg 
2589177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2590177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2591177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2592177f8f2bSJohan Hedberg {
2593177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2594177f8f2bSJohan Hedberg 	size_t pdu_len;
2595177f8f2bSJohan Hedberg 	u16 sdu_len;
2596177f8f2bSJohan Hedberg 
2597177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2598177f8f2bSJohan Hedberg 
2599177f8f2bSJohan Hedberg 	sdu_len = len;
260072c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2601177f8f2bSJohan Hedberg 
2602177f8f2bSJohan Hedberg 	while (len > 0) {
2603177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2604177f8f2bSJohan Hedberg 			pdu_len = len;
2605177f8f2bSJohan Hedberg 
2606177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2607177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2608177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2609177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2610177f8f2bSJohan Hedberg 		}
2611177f8f2bSJohan Hedberg 
2612177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2613177f8f2bSJohan Hedberg 
2614177f8f2bSJohan Hedberg 		len -= pdu_len;
2615177f8f2bSJohan Hedberg 
2616177f8f2bSJohan Hedberg 		if (sdu_len) {
2617177f8f2bSJohan Hedberg 			sdu_len = 0;
2618177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2619177f8f2bSJohan Hedberg 		}
2620177f8f2bSJohan Hedberg 	}
2621177f8f2bSJohan Hedberg 
2622177f8f2bSJohan Hedberg 	return 0;
2623177f8f2bSJohan Hedberg }
2624177f8f2bSJohan Hedberg 
26258a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
26268a505b7fSLuiz Augusto von Dentz {
26278a505b7fSLuiz Augusto von Dentz 	int sent = 0;
26288a505b7fSLuiz Augusto von Dentz 
26298a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
26308a505b7fSLuiz Augusto von Dentz 
26318a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
26328a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
26338a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
26348a505b7fSLuiz Augusto von Dentz 		sent++;
26358a505b7fSLuiz Augusto von Dentz 	}
26368a505b7fSLuiz Augusto von Dentz 
26378a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
26388a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
26398a505b7fSLuiz Augusto von Dentz }
26408a505b7fSLuiz Augusto von Dentz 
26418d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
26429a91a04aSGustavo F. Padovan {
26439a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26449a91a04aSGustavo F. Padovan 	int err;
264594122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26469a91a04aSGustavo F. Padovan 
264731e8ce80SSeung-Woo Kim 	if (!chan->conn)
264831e8ce80SSeung-Woo Kim 		return -ENOTCONN;
264931e8ce80SSeung-Woo Kim 
26509a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2651715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26528d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
26539a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26549a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26559a91a04aSGustavo F. Padovan 
2656ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2657ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2658ede81a2aSAndrzej Kaczmarek 		 */
2659ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2660ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2661ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2662ede81a2aSAndrzej Kaczmarek 		}
2663ede81a2aSAndrzej Kaczmarek 
26649a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26659a91a04aSGustavo F. Padovan 		return len;
26669a91a04aSGustavo F. Padovan 	}
26679a91a04aSGustavo F. Padovan 
26689a91a04aSGustavo F. Padovan 	switch (chan->mode) {
266938319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
267015f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
2671177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2672177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2673177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2674177f8f2bSJohan Hedberg 
2675177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2676177f8f2bSJohan Hedberg 
2677177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2678177f8f2bSJohan Hedberg 
2679177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2680177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2681177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2682177f8f2bSJohan Hedberg 		}
2683177f8f2bSJohan Hedberg 
2684177f8f2bSJohan Hedberg 		if (err)
2685177f8f2bSJohan Hedberg 			return err;
2686177f8f2bSJohan Hedberg 
2687177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2688177f8f2bSJohan Hedberg 
26898a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2690177f8f2bSJohan Hedberg 
2691177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2692177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2693177f8f2bSJohan Hedberg 
2694177f8f2bSJohan Hedberg 		err = len;
2695177f8f2bSJohan Hedberg 
2696177f8f2bSJohan Hedberg 		break;
2697177f8f2bSJohan Hedberg 
2698fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
26999a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
27009a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
27019a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
27029a91a04aSGustavo F. Padovan 
27039a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
27048d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
27059a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
27069a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
27079a91a04aSGustavo F. Padovan 
2708ede81a2aSAndrzej Kaczmarek 		/* Channel lock is released before requesting new skb and then
2709ede81a2aSAndrzej Kaczmarek 		 * reacquired thus we need to recheck channel state.
2710ede81a2aSAndrzej Kaczmarek 		 */
2711ede81a2aSAndrzej Kaczmarek 		if (chan->state != BT_CONNECTED) {
2712ede81a2aSAndrzej Kaczmarek 			kfree_skb(skb);
2713ede81a2aSAndrzej Kaczmarek 			return -ENOTCONN;
2714ede81a2aSAndrzej Kaczmarek 		}
2715ede81a2aSAndrzej Kaczmarek 
27169a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
27179a91a04aSGustavo F. Padovan 		err = len;
27189a91a04aSGustavo F. Padovan 		break;
27199a91a04aSGustavo F. Padovan 
27209a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27219a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
272294122bbeSMat Martineau 		/* Check outgoing MTU */
272394122bbeSMat Martineau 		if (len > chan->omtu) {
272494122bbeSMat Martineau 			err = -EMSGSIZE;
27259a91a04aSGustavo F. Padovan 			break;
27269a91a04aSGustavo F. Padovan 		}
27279a91a04aSGustavo F. Padovan 
272894122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
272994122bbeSMat Martineau 
273094122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
273194122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
273294122bbeSMat Martineau 		 * allocation.
273394122bbeSMat Martineau 		 */
273494122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
273594122bbeSMat Martineau 
273694122bbeSMat Martineau 		/* The channel could have been closed while segmenting,
273794122bbeSMat Martineau 		 * check that it is still connected.
273894122bbeSMat Martineau 		 */
273994122bbeSMat Martineau 		if (chan->state != BT_CONNECTED) {
274094122bbeSMat Martineau 			__skb_queue_purge(&seg_queue);
274194122bbeSMat Martineau 			err = -ENOTCONN;
27429a91a04aSGustavo F. Padovan 		}
27439a91a04aSGustavo F. Padovan 
274494122bbeSMat Martineau 		if (err)
274594122bbeSMat Martineau 			break;
274694122bbeSMat Martineau 
27473733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2748d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27493733937dSMat Martineau 		else
2750d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
275194122bbeSMat Martineau 
27529a91a04aSGustavo F. Padovan 		err = len;
27539a91a04aSGustavo F. Padovan 
275494122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
275594122bbeSMat Martineau 		 * seg_queue and need to be purged.
275694122bbeSMat Martineau 		 */
275794122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27589a91a04aSGustavo F. Padovan 		break;
27599a91a04aSGustavo F. Padovan 
27609a91a04aSGustavo F. Padovan 	default:
27619a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27629a91a04aSGustavo F. Padovan 		err = -EBADFD;
27639a91a04aSGustavo F. Padovan 	}
27649a91a04aSGustavo F. Padovan 
27659a91a04aSGustavo F. Padovan 	return err;
27669a91a04aSGustavo F. Padovan }
27676b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
27689a91a04aSGustavo F. Padovan 
2769d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2770d2a7ac5dSMat Martineau {
2771bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2772bed68bdeSMat Martineau 	u16 seq;
2773bed68bdeSMat Martineau 
2774b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2775bed68bdeSMat Martineau 
2776bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2777bed68bdeSMat Martineau 	control.sframe = 1;
2778bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2779bed68bdeSMat Martineau 
2780bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2781bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2782bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2783bed68bdeSMat Martineau 			control.reqseq = seq;
2784bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2785bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2786bed68bdeSMat Martineau 		}
2787bed68bdeSMat Martineau 	}
2788bed68bdeSMat Martineau 
2789bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2790d2a7ac5dSMat Martineau }
2791d2a7ac5dSMat Martineau 
2792d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2793d2a7ac5dSMat Martineau {
2794bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2795bed68bdeSMat Martineau 
2796bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2797bed68bdeSMat Martineau 
2798bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2799bed68bdeSMat Martineau 		return;
2800bed68bdeSMat Martineau 
2801bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2802bed68bdeSMat Martineau 	control.sframe = 1;
2803bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2804bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2805bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2806d2a7ac5dSMat Martineau }
2807d2a7ac5dSMat Martineau 
2808d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2809d2a7ac5dSMat Martineau {
2810bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2811bed68bdeSMat Martineau 	u16 initial_head;
2812bed68bdeSMat Martineau 	u16 seq;
2813bed68bdeSMat Martineau 
2814b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2815bed68bdeSMat Martineau 
2816bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2817bed68bdeSMat Martineau 	control.sframe = 1;
2818bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2819bed68bdeSMat Martineau 
2820bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2821bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2822bed68bdeSMat Martineau 
2823bed68bdeSMat Martineau 	do {
2824bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2825bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2826bed68bdeSMat Martineau 			break;
2827bed68bdeSMat Martineau 
2828bed68bdeSMat Martineau 		control.reqseq = seq;
2829bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2830bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2831bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2832d2a7ac5dSMat Martineau }
2833d2a7ac5dSMat Martineau 
2834608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2835608bcc6dSMat Martineau {
2836608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2837608bcc6dSMat Martineau 	u16 ackseq;
2838608bcc6dSMat Martineau 
2839b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2840608bcc6dSMat Martineau 
2841608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2842608bcc6dSMat Martineau 		return;
2843608bcc6dSMat Martineau 
2844b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2845608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2846608bcc6dSMat Martineau 
2847608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2848608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2849608bcc6dSMat Martineau 
2850608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2851608bcc6dSMat Martineau 		if (acked_skb) {
2852608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2853608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2854608bcc6dSMat Martineau 			chan->unacked_frames--;
2855608bcc6dSMat Martineau 		}
2856608bcc6dSMat Martineau 	}
2857608bcc6dSMat Martineau 
2858608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2859608bcc6dSMat Martineau 
2860608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2861608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2862608bcc6dSMat Martineau 
2863b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2864608bcc6dSMat Martineau }
2865608bcc6dSMat Martineau 
2866608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2867608bcc6dSMat Martineau {
2868608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2869608bcc6dSMat Martineau 
2870608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2871608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2872608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2873608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2874608bcc6dSMat Martineau }
2875608bcc6dSMat Martineau 
2876d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2877608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2878608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2879608bcc6dSMat Martineau {
2880608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2881608bcc6dSMat Martineau 	       event);
2882608bcc6dSMat Martineau 
2883608bcc6dSMat Martineau 	switch (event) {
2884608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2885608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2886608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2887608bcc6dSMat Martineau 
2888608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2889608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2890608bcc6dSMat Martineau 		break;
2891608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2892608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2893608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2894608bcc6dSMat Martineau 
2895608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2896608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2897608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2898608bcc6dSMat Martineau 			 */
2899608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2900608bcc6dSMat Martineau 		}
2901608bcc6dSMat Martineau 
2902608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2903608bcc6dSMat Martineau 
2904608bcc6dSMat Martineau 		break;
2905608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2906608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2907608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2908608bcc6dSMat Martineau 
2909608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2910608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2911608bcc6dSMat Martineau 
2912608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2913608bcc6dSMat Martineau 			local_control.sframe = 1;
2914608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2915608bcc6dSMat Martineau 			local_control.poll = 1;
2916608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2917a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2918608bcc6dSMat Martineau 
2919608bcc6dSMat Martineau 			chan->retry_count = 1;
2920608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2921608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2922608bcc6dSMat Martineau 		}
2923608bcc6dSMat Martineau 		break;
2924608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2925608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2926608bcc6dSMat Martineau 		break;
2927608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2928608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2929608bcc6dSMat Martineau 		chan->retry_count = 1;
2930608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2931608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2932608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2933608bcc6dSMat Martineau 		break;
2934608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2935608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2936608bcc6dSMat Martineau 		chan->retry_count = 1;
2937608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2938608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2939608bcc6dSMat Martineau 		break;
2940608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2941608bcc6dSMat Martineau 		/* Nothing to process */
2942608bcc6dSMat Martineau 		break;
2943608bcc6dSMat Martineau 	default:
2944608bcc6dSMat Martineau 		break;
2945608bcc6dSMat Martineau 	}
2946608bcc6dSMat Martineau }
2947608bcc6dSMat Martineau 
2948d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2949608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2950608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2951608bcc6dSMat Martineau {
2952608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2953608bcc6dSMat Martineau 	       event);
2954608bcc6dSMat Martineau 
2955608bcc6dSMat Martineau 	switch (event) {
2956608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2957608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2958608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2959608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2960608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2961608bcc6dSMat Martineau 		break;
2962608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2963608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2964608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2965608bcc6dSMat Martineau 
2966608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2967608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2968608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2969608bcc6dSMat Martineau 			 */
2970608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2971608bcc6dSMat Martineau 		}
2972608bcc6dSMat Martineau 
2973608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2974608bcc6dSMat Martineau 
2975608bcc6dSMat Martineau 		break;
2976608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2977608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2978608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2979608bcc6dSMat Martineau 
2980608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2981608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2982608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2983608bcc6dSMat Martineau 			local_control.sframe = 1;
2984608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2985608bcc6dSMat Martineau 			local_control.poll = 1;
2986608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2987a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2988608bcc6dSMat Martineau 
2989608bcc6dSMat Martineau 			chan->retry_count = 1;
2990608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2991608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2992608bcc6dSMat Martineau 		}
2993608bcc6dSMat Martineau 		break;
2994608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2995608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
299619186c7bSGustavo A. R. Silva 		fallthrough;
2997608bcc6dSMat Martineau 
2998608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2999608bcc6dSMat Martineau 		if (control && control->final) {
3000608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
3001608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
3002608bcc6dSMat Martineau 				__set_retrans_timer(chan);
3003608bcc6dSMat Martineau 			chan->retry_count = 0;
3004608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
3005608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
3006608bcc6dSMat Martineau 		}
3007608bcc6dSMat Martineau 		break;
3008608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
3009608bcc6dSMat Martineau 		/* Ignore */
3010608bcc6dSMat Martineau 		break;
3011608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
3012608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
3013608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
3014608bcc6dSMat Martineau 			__set_monitor_timer(chan);
3015608bcc6dSMat Martineau 			chan->retry_count++;
3016608bcc6dSMat Martineau 		} else {
30175e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
3018608bcc6dSMat Martineau 		}
3019608bcc6dSMat Martineau 		break;
3020608bcc6dSMat Martineau 	default:
3021608bcc6dSMat Martineau 		break;
3022608bcc6dSMat Martineau 	}
3023608bcc6dSMat Martineau }
3024608bcc6dSMat Martineau 
3025d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
3026608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
3027608bcc6dSMat Martineau {
3028608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
3029608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
3030608bcc6dSMat Martineau 
3031608bcc6dSMat Martineau 	switch (chan->tx_state) {
3032608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3033d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3034608bcc6dSMat Martineau 		break;
3035608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3036d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3037608bcc6dSMat Martineau 		break;
3038608bcc6dSMat Martineau 	default:
3039608bcc6dSMat Martineau 		/* Ignore event */
3040608bcc6dSMat Martineau 		break;
3041608bcc6dSMat Martineau 	}
3042608bcc6dSMat Martineau }
3043608bcc6dSMat Martineau 
30444b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30454b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30464b51dae9SMat Martineau {
30474b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3048401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30494b51dae9SMat Martineau }
30504b51dae9SMat Martineau 
3051f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3052f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3053f80842a8SMat Martineau {
3054f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3055401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3056f80842a8SMat Martineau }
3057f80842a8SMat Martineau 
30580a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30590a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30600a708f8fSGustavo F. Padovan {
30610a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
306248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30630a708f8fSGustavo F. Padovan 
30640a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30650a708f8fSGustavo F. Padovan 
30663df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30673d57dc68SGustavo F. Padovan 
30683df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3069715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30700a708f8fSGustavo F. Padovan 			continue;
30710a708f8fSGustavo F. Padovan 
30727f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
3073a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
30740a708f8fSGustavo F. Padovan 			continue;
30757f5396a7SGustavo Padovan 
30768bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30770a708f8fSGustavo F. Padovan 		if (!nskb)
30780a708f8fSGustavo F. Padovan 			continue;
307980b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30800a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30810a708f8fSGustavo F. Padovan 	}
30823d57dc68SGustavo F. Padovan 
30833df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30840a708f8fSGustavo F. Padovan }
30850a708f8fSGustavo F. Padovan 
30860a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3087b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3088b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30890a708f8fSGustavo F. Padovan {
30900a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30910a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30920a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30930a708f8fSGustavo F. Padovan 	int len, count;
30940a708f8fSGustavo F. Padovan 
3095b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30960a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
30970a708f8fSGustavo F. Padovan 
3098300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3099300b962eSAnderson Lizardo 		return NULL;
3100300b962eSAnderson Lizardo 
31010a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
31020a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
31030a708f8fSGustavo F. Padovan 
31048bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
31050a708f8fSGustavo F. Padovan 	if (!skb)
31060a708f8fSGustavo F. Padovan 		return NULL;
31070a708f8fSGustavo F. Padovan 
31084df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
31090a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
31103300d9a9SClaudio Takahasi 
31113300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3112dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
31133300d9a9SClaudio Takahasi 	else
3114dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
31150a708f8fSGustavo F. Padovan 
31164df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
31170a708f8fSGustavo F. Padovan 	cmd->code  = code;
31180a708f8fSGustavo F. Padovan 	cmd->ident = ident;
31190a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
31200a708f8fSGustavo F. Padovan 
31210a708f8fSGustavo F. Padovan 	if (dlen) {
31220a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
312359ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
31240a708f8fSGustavo F. Padovan 		data += count;
31250a708f8fSGustavo F. Padovan 	}
31260a708f8fSGustavo F. Padovan 
31270a708f8fSGustavo F. Padovan 	len -= skb->len;
31280a708f8fSGustavo F. Padovan 
31290a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
31300a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31310a708f8fSGustavo F. Padovan 	while (len) {
31320a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31330a708f8fSGustavo F. Padovan 
31348bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31350a708f8fSGustavo F. Padovan 		if (!*frag)
31360a708f8fSGustavo F. Padovan 			goto fail;
31370a708f8fSGustavo F. Padovan 
313859ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
31390a708f8fSGustavo F. Padovan 
31400a708f8fSGustavo F. Padovan 		len  -= count;
31410a708f8fSGustavo F. Padovan 		data += count;
31420a708f8fSGustavo F. Padovan 
31430a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31440a708f8fSGustavo F. Padovan 	}
31450a708f8fSGustavo F. Padovan 
31460a708f8fSGustavo F. Padovan 	return skb;
31470a708f8fSGustavo F. Padovan 
31480a708f8fSGustavo F. Padovan fail:
31490a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31500a708f8fSGustavo F. Padovan 	return NULL;
31510a708f8fSGustavo F. Padovan }
31520a708f8fSGustavo F. Padovan 
31532d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31542d792818SGustavo Padovan 				     unsigned long *val)
31550a708f8fSGustavo F. Padovan {
31560a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31570a708f8fSGustavo F. Padovan 	int len;
31580a708f8fSGustavo F. Padovan 
31590a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31600a708f8fSGustavo F. Padovan 	*ptr += len;
31610a708f8fSGustavo F. Padovan 
31620a708f8fSGustavo F. Padovan 	*type = opt->type;
31630a708f8fSGustavo F. Padovan 	*olen = opt->len;
31640a708f8fSGustavo F. Padovan 
31650a708f8fSGustavo F. Padovan 	switch (opt->len) {
31660a708f8fSGustavo F. Padovan 	case 1:
31670a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31680a708f8fSGustavo F. Padovan 		break;
31690a708f8fSGustavo F. Padovan 
31700a708f8fSGustavo F. Padovan 	case 2:
31710a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31720a708f8fSGustavo F. Padovan 		break;
31730a708f8fSGustavo F. Padovan 
31740a708f8fSGustavo F. Padovan 	case 4:
31750a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31760a708f8fSGustavo F. Padovan 		break;
31770a708f8fSGustavo F. Padovan 
31780a708f8fSGustavo F. Padovan 	default:
31790a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31800a708f8fSGustavo F. Padovan 		break;
31810a708f8fSGustavo F. Padovan 	}
31820a708f8fSGustavo F. Padovan 
3183b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31840a708f8fSGustavo F. Padovan 	return len;
31850a708f8fSGustavo F. Padovan }
31860a708f8fSGustavo F. Padovan 
3187e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
31880a708f8fSGustavo F. Padovan {
31890a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31900a708f8fSGustavo F. Padovan 
3191b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31920a708f8fSGustavo F. Padovan 
3193e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3194e860d2c9SBen Seri 		return;
3195e860d2c9SBen Seri 
31960a708f8fSGustavo F. Padovan 	opt->type = type;
31970a708f8fSGustavo F. Padovan 	opt->len  = len;
31980a708f8fSGustavo F. Padovan 
31990a708f8fSGustavo F. Padovan 	switch (len) {
32000a708f8fSGustavo F. Padovan 	case 1:
32010a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
32020a708f8fSGustavo F. Padovan 		break;
32030a708f8fSGustavo F. Padovan 
32040a708f8fSGustavo F. Padovan 	case 2:
32050a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
32060a708f8fSGustavo F. Padovan 		break;
32070a708f8fSGustavo F. Padovan 
32080a708f8fSGustavo F. Padovan 	case 4:
32090a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
32100a708f8fSGustavo F. Padovan 		break;
32110a708f8fSGustavo F. Padovan 
32120a708f8fSGustavo F. Padovan 	default:
32130a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
32140a708f8fSGustavo F. Padovan 		break;
32150a708f8fSGustavo F. Padovan 	}
32160a708f8fSGustavo F. Padovan 
32170a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
32180a708f8fSGustavo F. Padovan }
32190a708f8fSGustavo F. Padovan 
3220e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3221f89cef09SAndrei Emeltchenko {
3222f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3223f89cef09SAndrei Emeltchenko 
3224f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3225f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3226f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3227f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3228f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3229f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3230dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3231dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3232f89cef09SAndrei Emeltchenko 		break;
3233f89cef09SAndrei Emeltchenko 
3234f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3235f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3236f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3237f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3238f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3239f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3240f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3241f89cef09SAndrei Emeltchenko 		break;
3242f89cef09SAndrei Emeltchenko 
3243f89cef09SAndrei Emeltchenko 	default:
3244f89cef09SAndrei Emeltchenko 		return;
3245f89cef09SAndrei Emeltchenko 	}
3246f89cef09SAndrei Emeltchenko 
3247f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3248e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3249f89cef09SAndrei Emeltchenko }
3250f89cef09SAndrei Emeltchenko 
3251721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32520a708f8fSGustavo F. Padovan {
3253721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3254721c4181SGustavo F. Padovan 					       ack_timer.work);
32550362520bSMat Martineau 	u16 frames_to_ack;
32560a708f8fSGustavo F. Padovan 
32572fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32582fb9b3d4SGustavo F. Padovan 
32596be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32606be36555SAndrei Emeltchenko 
32610362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32620362520bSMat Martineau 				     chan->last_acked_seq);
32630362520bSMat Martineau 
32640362520bSMat Martineau 	if (frames_to_ack)
32650362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32666be36555SAndrei Emeltchenko 
32676be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
326809bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32690a708f8fSGustavo F. Padovan }
32700a708f8fSGustavo F. Padovan 
3271466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32720a708f8fSGustavo F. Padovan {
32733c588192SMat Martineau 	int err;
32743c588192SMat Martineau 
3275105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3276105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
327742e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32786a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
327942e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32806a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3281105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3282105bdf9eSMat Martineau 	chan->sdu = NULL;
3283105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3284105bdf9eSMat Martineau 	chan->sdu_len = 0;
3285105bdf9eSMat Martineau 
3286d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3287d34c34fbSMat Martineau 
32886ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32896ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
329008333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
329108333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
329208333283SMat Martineau 
3293105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3294105bdf9eSMat Martineau 		return 0;
3295105bdf9eSMat Martineau 
3296105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3297105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
32980a708f8fSGustavo F. Padovan 
3299721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
3300721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
3301721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
33020a708f8fSGustavo F. Padovan 
3303f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
33040a708f8fSGustavo F. Padovan 
33053c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
33063c588192SMat Martineau 	if (err < 0)
33073c588192SMat Martineau 		return err;
33083c588192SMat Martineau 
33099dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
33109dc9affcSMat Martineau 	if (err < 0)
33119dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
33129dc9affcSMat Martineau 
33139dc9affcSMat Martineau 	return err;
33140a708f8fSGustavo F. Padovan }
33150a708f8fSGustavo F. Padovan 
33160a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
33170a708f8fSGustavo F. Padovan {
33180a708f8fSGustavo F. Padovan 	switch (mode) {
33190a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33200a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33210a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
33220a708f8fSGustavo F. Padovan 			return mode;
332319186c7bSGustavo A. R. Silva 		fallthrough;
33240a708f8fSGustavo F. Padovan 	default:
33250a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
33260a708f8fSGustavo F. Padovan 	}
33270a708f8fSGustavo F. Padovan }
33280a708f8fSGustavo F. Padovan 
3329848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
33306327eb98SAndrei Emeltchenko {
33310bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33320bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
33336327eb98SAndrei Emeltchenko }
33346327eb98SAndrei Emeltchenko 
3335848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3336f89cef09SAndrei Emeltchenko {
33370bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33380bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3339f89cef09SAndrei Emeltchenko }
3340f89cef09SAndrei Emeltchenko 
334136c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
334236c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
334336c86c85SMat Martineau {
33446ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
334536c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
334636c86c85SMat Martineau 
334736c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
334836c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
334936c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
335036c86c85SMat Martineau 		 * controllers is 10 seconds.
335136c86c85SMat Martineau 		 *
335236c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
335336c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
335436c86c85SMat Martineau 		 * will result in a timeout that meets the above
335536c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
335636c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
335736c86c85SMat Martineau 		 */
335836c86c85SMat Martineau 
335936c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
336036c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
336136c86c85SMat Martineau 
336236c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
336336c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
336436c86c85SMat Martineau 		 * controller.
336536c86c85SMat Martineau 		 */
336636c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
336736c86c85SMat Martineau 
336836c86c85SMat Martineau 		if (ertm_to > 0xffff)
336936c86c85SMat Martineau 			ertm_to = 0xffff;
337036c86c85SMat Martineau 
337136c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
337236c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
337336c86c85SMat Martineau 	} else {
3374dcf4adbfSJoe Perches 		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3375dcf4adbfSJoe Perches 		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
337636c86c85SMat Martineau 	}
337736c86c85SMat Martineau }
337836c86c85SMat Martineau 
33796327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33806327eb98SAndrei Emeltchenko {
33816327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3382848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33836327eb98SAndrei Emeltchenko 		/* use extended control field */
33846327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3385836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3386836be934SAndrei Emeltchenko 	} else {
33876327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33886327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3389836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3390836be934SAndrei Emeltchenko 	}
3391c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33926327eb98SAndrei Emeltchenko }
33936327eb98SAndrei Emeltchenko 
33944b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
33954b6e228eSLuiz Augusto von Dentz {
33964b6e228eSLuiz Augusto von Dentz 	struct hci_conn *conn = chan->conn->hcon;
33974b6e228eSLuiz Augusto von Dentz 
33984b6e228eSLuiz Augusto von Dentz 	chan->imtu = L2CAP_DEFAULT_MIN_MTU;
33994b6e228eSLuiz Augusto von Dentz 
34004b6e228eSLuiz Augusto von Dentz 	/* The 2-DH1 packet has between 2 and 56 information bytes
34014b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34024b6e228eSLuiz Augusto von Dentz 	 */
34034b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH1))
34044b6e228eSLuiz Augusto von Dentz 		chan->imtu = 54;
34054b6e228eSLuiz Augusto von Dentz 
34064b6e228eSLuiz Augusto von Dentz 	/* The 3-DH1 packet has between 2 and 85 information bytes
34074b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34084b6e228eSLuiz Augusto von Dentz 	 */
34094b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH1))
34104b6e228eSLuiz Augusto von Dentz 		chan->imtu = 83;
34114b6e228eSLuiz Augusto von Dentz 
34124b6e228eSLuiz Augusto von Dentz 	/* The 2-DH3 packet has between 2 and 369 information bytes
34134b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34144b6e228eSLuiz Augusto von Dentz 	 */
34154b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH3))
34164b6e228eSLuiz Augusto von Dentz 		chan->imtu = 367;
34174b6e228eSLuiz Augusto von Dentz 
34184b6e228eSLuiz Augusto von Dentz 	/* The 3-DH3 packet has between 2 and 554 information bytes
34194b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34204b6e228eSLuiz Augusto von Dentz 	 */
34214b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH3))
34224b6e228eSLuiz Augusto von Dentz 		chan->imtu = 552;
34234b6e228eSLuiz Augusto von Dentz 
34244b6e228eSLuiz Augusto von Dentz 	/* The 2-DH5 packet has between 2 and 681 information bytes
34254b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34264b6e228eSLuiz Augusto von Dentz 	 */
34274b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH5))
34284b6e228eSLuiz Augusto von Dentz 		chan->imtu = 679;
34294b6e228eSLuiz Augusto von Dentz 
34304b6e228eSLuiz Augusto von Dentz 	/* The 3-DH5 packet has between 2 and 1023 information bytes
34314b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34324b6e228eSLuiz Augusto von Dentz 	 */
34334b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH5))
34344b6e228eSLuiz Augusto von Dentz 		chan->imtu = 1021;
34354b6e228eSLuiz Augusto von Dentz }
34364b6e228eSLuiz Augusto von Dentz 
3437e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
34380a708f8fSGustavo F. Padovan {
34390a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
34400c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
34410a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3442e860d2c9SBen Seri 	void *endptr = data + data_size;
3443c8f79162SAndrei Emeltchenko 	u16 size;
34440a708f8fSGustavo F. Padovan 
344549208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
34460a708f8fSGustavo F. Padovan 
344773ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
34480a708f8fSGustavo F. Padovan 		goto done;
34490a708f8fSGustavo F. Padovan 
34500c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34510a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34520a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3453c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
34540a708f8fSGustavo F. Padovan 			break;
34550a708f8fSGustavo F. Padovan 
3456848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3457f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3458f89cef09SAndrei Emeltchenko 
345919186c7bSGustavo A. R. Silva 		fallthrough;
34600a708f8fSGustavo F. Padovan 	default:
34618c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
34620a708f8fSGustavo F. Padovan 		break;
34630a708f8fSGustavo F. Padovan 	}
34640a708f8fSGustavo F. Padovan 
34650a708f8fSGustavo F. Padovan done:
34664b6e228eSLuiz Augusto von Dentz 	if (chan->imtu != L2CAP_DEFAULT_MTU) {
34674b6e228eSLuiz Augusto von Dentz 		if (!chan->imtu)
34684b6e228eSLuiz Augusto von Dentz 			l2cap_mtu_auto(chan);
34694b6e228eSLuiz Augusto von Dentz 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
34704b6e228eSLuiz Augusto von Dentz 				   endptr - ptr);
34714b6e228eSLuiz Augusto von Dentz 	}
34720a708f8fSGustavo F. Padovan 
34730c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34740a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
34756fea7ad1SMarcel Holtmann 		if (disable_ertm)
34766fea7ad1SMarcel Holtmann 			break;
34776fea7ad1SMarcel Holtmann 
34788c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
34798c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
34800a708f8fSGustavo F. Padovan 			break;
34810a708f8fSGustavo F. Padovan 
34820a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
34830a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34840a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34850a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34860a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34870a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34880a708f8fSGustavo F. Padovan 
34890a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3490e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34910a708f8fSGustavo F. Padovan 		break;
34920a708f8fSGustavo F. Padovan 
34930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34940a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
349547d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
349636c86c85SMat Martineau 
349736c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3498c8f79162SAndrei Emeltchenko 
3499c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
35002d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3501c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3502c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35030a708f8fSGustavo F. Padovan 
35046327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
35056327eb98SAndrei Emeltchenko 
35066327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
35076327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
35080a708f8fSGustavo F. Padovan 
35090a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3510e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35110a708f8fSGustavo F. Padovan 
3512f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3513e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3514f89cef09SAndrei Emeltchenko 
35156327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
35166327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3517e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
351860918918SAndrei Emeltchenko 
351960918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
352060918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3521f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
352260918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
352360918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3524e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
352560918918SAndrei Emeltchenko 			}
35260a708f8fSGustavo F. Padovan 		break;
35270a708f8fSGustavo F. Padovan 
35280a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3529273759e2SMat Martineau 		l2cap_txwin_setup(chan);
35300a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
35310a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
35320a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
35330a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
35340a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3535c8f79162SAndrei Emeltchenko 
3536c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
35372d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3538c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3539c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35400a708f8fSGustavo F. Padovan 
35410a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3542e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35430a708f8fSGustavo F. Padovan 
3544f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3545e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3546f89cef09SAndrei Emeltchenko 
354760918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
354847d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3549f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
355047d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
355160918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3552e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
35530a708f8fSGustavo F. Padovan 			}
35540a708f8fSGustavo F. Padovan 		break;
35550a708f8fSGustavo F. Padovan 	}
35560a708f8fSGustavo F. Padovan 
3557fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3558dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
35590a708f8fSGustavo F. Padovan 
35600a708f8fSGustavo F. Padovan 	return ptr - data;
35610a708f8fSGustavo F. Padovan }
35620a708f8fSGustavo F. Padovan 
3563e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
35640a708f8fSGustavo F. Padovan {
35650a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
35660a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3567e860d2c9SBen Seri 	void *endptr = data + data_size;
356873ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
356973ffa904SGustavo F. Padovan 	int len = chan->conf_len;
35700a708f8fSGustavo F. Padovan 	int type, hint, olen;
35710a708f8fSGustavo F. Padovan 	unsigned long val;
35720a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
357342dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
357442dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
35750a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
35760a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3577c8f79162SAndrei Emeltchenko 	u16 size;
35780a708f8fSGustavo F. Padovan 
357973ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
35800a708f8fSGustavo F. Padovan 
35810a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35820a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
35837c9cbd0bSMarcel Holtmann 		if (len < 0)
35847c9cbd0bSMarcel Holtmann 			break;
35850a708f8fSGustavo F. Padovan 
35860a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
35870a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
35880a708f8fSGustavo F. Padovan 
35890a708f8fSGustavo F. Padovan 		switch (type) {
35900a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3591af3d5d1cSMarcel Holtmann 			if (olen != 2)
3592af3d5d1cSMarcel Holtmann 				break;
35930a708f8fSGustavo F. Padovan 			mtu = val;
35940a708f8fSGustavo F. Padovan 			break;
35950a708f8fSGustavo F. Padovan 
35960a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3597af3d5d1cSMarcel Holtmann 			if (olen != 2)
3598af3d5d1cSMarcel Holtmann 				break;
35990c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
36000a708f8fSGustavo F. Padovan 			break;
36010a708f8fSGustavo F. Padovan 
36020a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
36030a708f8fSGustavo F. Padovan 			break;
36040a708f8fSGustavo F. Padovan 
36050a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3606af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3607af3d5d1cSMarcel Holtmann 				break;
36080a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
36090a708f8fSGustavo F. Padovan 			break;
36100a708f8fSGustavo F. Padovan 
36110a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3612af3d5d1cSMarcel Holtmann 			if (olen != 1)
3613af3d5d1cSMarcel Holtmann 				break;
36140a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3615f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
361642dceae2SAndrei Emeltchenko 			break;
36170a708f8fSGustavo F. Padovan 
361842dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3619af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3620af3d5d1cSMarcel Holtmann 				break;
362142dceae2SAndrei Emeltchenko 			remote_efs = 1;
362242dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
36230a708f8fSGustavo F. Padovan 			break;
36240a708f8fSGustavo F. Padovan 
36256327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3626af3d5d1cSMarcel Holtmann 			if (olen != 2)
3627af3d5d1cSMarcel Holtmann 				break;
36280bd49fc7SJohan Hedberg 			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
36296327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
36306327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
36316327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3632836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
36336327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
36340a708f8fSGustavo F. Padovan 			break;
36350a708f8fSGustavo F. Padovan 
36360a708f8fSGustavo F. Padovan 		default:
36370a708f8fSGustavo F. Padovan 			if (hint)
36380a708f8fSGustavo F. Padovan 				break;
36390a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
36405b8ec15dSJimmy Wahlberg 			l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
36410a708f8fSGustavo F. Padovan 			break;
36420a708f8fSGustavo F. Padovan 		}
36430a708f8fSGustavo F. Padovan 	}
36440a708f8fSGustavo F. Padovan 
364573ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
36460a708f8fSGustavo F. Padovan 		goto done;
36470a708f8fSGustavo F. Padovan 
36480c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
36490a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
36500a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3651c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
36520c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
36538c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
36540a708f8fSGustavo F. Padovan 			break;
36550a708f8fSGustavo F. Padovan 		}
36560a708f8fSGustavo F. Padovan 
365742dceae2SAndrei Emeltchenko 		if (remote_efs) {
3658848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
365942dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
366042dceae2SAndrei Emeltchenko 			else
366142dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
366242dceae2SAndrei Emeltchenko 		}
366342dceae2SAndrei Emeltchenko 
36640c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
36650a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36660a708f8fSGustavo F. Padovan 
36670a708f8fSGustavo F. Padovan 		break;
36680a708f8fSGustavo F. Padovan 	}
36690a708f8fSGustavo F. Padovan 
36700a708f8fSGustavo F. Padovan done:
36710c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
36720a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
36730c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
36740a708f8fSGustavo F. Padovan 
367573ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
36760a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36770a708f8fSGustavo F. Padovan 
36782d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3679e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
36800a708f8fSGustavo F. Padovan 	}
36810a708f8fSGustavo F. Padovan 
36820a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
36830a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
36840a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
36850a708f8fSGustavo F. Padovan 
36860a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
36870a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36880a708f8fSGustavo F. Padovan 		else {
36890c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3690c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
36910a708f8fSGustavo F. Padovan 		}
3692e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
36930a708f8fSGustavo F. Padovan 
369442dceae2SAndrei Emeltchenko 		if (remote_efs) {
369542dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
369642dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
369742dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
369842dceae2SAndrei Emeltchenko 
369942dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
370042dceae2SAndrei Emeltchenko 
370142dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
370242dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
370342dceae2SAndrei Emeltchenko 
370442dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
370542dceae2SAndrei Emeltchenko 						   sizeof(efs),
3706e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
37070e8b207eSAndrei Emeltchenko 			} else {
37083e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
37090e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
37100e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
371142dceae2SAndrei Emeltchenko 			}
371242dceae2SAndrei Emeltchenko 		}
371342dceae2SAndrei Emeltchenko 
37140a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37150a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
371647d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3717c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37180a708f8fSGustavo F. Padovan 			break;
37190a708f8fSGustavo F. Padovan 
37200a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
37216327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
37222c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
37236327eb98SAndrei Emeltchenko 			else
37246327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
37256327eb98SAndrei Emeltchenko 
37262c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
37270a708f8fSGustavo F. Padovan 
3728c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
37292d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
37302d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3731c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3732c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
37330a708f8fSGustavo F. Padovan 
373436c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
37350a708f8fSGustavo F. Padovan 
3736c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37370a708f8fSGustavo F. Padovan 
37380a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3739e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
37400a708f8fSGustavo F. Padovan 
374142dceae2SAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
374242dceae2SAndrei Emeltchenko 				chan->remote_id = efs.id;
374342dceae2SAndrei Emeltchenko 				chan->remote_stype = efs.stype;
374442dceae2SAndrei Emeltchenko 				chan->remote_msdu = le16_to_cpu(efs.msdu);
374542dceae2SAndrei Emeltchenko 				chan->remote_flush_to =
374642dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
374742dceae2SAndrei Emeltchenko 				chan->remote_acc_lat =
374842dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.acc_lat);
374942dceae2SAndrei Emeltchenko 				chan->remote_sdu_itime =
375042dceae2SAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
375142dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
37522d792818SGustavo Padovan 						   sizeof(efs),
3753e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
375442dceae2SAndrei Emeltchenko 			}
37550a708f8fSGustavo F. Padovan 			break;
37560a708f8fSGustavo F. Padovan 
37570a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
3758c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
37592d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
37602d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3761c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3762c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
37630a708f8fSGustavo F. Padovan 
3764c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37650a708f8fSGustavo F. Padovan 
37662d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3767e860d2c9SBen Seri 					   (unsigned long) &rfc, endptr - ptr);
37680a708f8fSGustavo F. Padovan 
37690a708f8fSGustavo F. Padovan 			break;
37700a708f8fSGustavo F. Padovan 
37710a708f8fSGustavo F. Padovan 		default:
37720a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
37730a708f8fSGustavo F. Padovan 
37740a708f8fSGustavo F. Padovan 			memset(&rfc, 0, sizeof(rfc));
37750c1bc5c6SGustavo F. Padovan 			rfc.mode = chan->mode;
37760a708f8fSGustavo F. Padovan 		}
37770a708f8fSGustavo F. Padovan 
37780a708f8fSGustavo F. Padovan 		if (result == L2CAP_CONF_SUCCESS)
3779c1360a1cSGustavo F. Padovan 			set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
37800a708f8fSGustavo F. Padovan 	}
3781fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
37820a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
3783dcf4adbfSJoe Perches 	rsp->flags  = cpu_to_le16(0);
37840a708f8fSGustavo F. Padovan 
37850a708f8fSGustavo F. Padovan 	return ptr - data;
37860a708f8fSGustavo F. Padovan }
37870a708f8fSGustavo F. Padovan 
37882d792818SGustavo Padovan static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3789e860d2c9SBen Seri 				void *data, size_t size, u16 *result)
37900a708f8fSGustavo F. Padovan {
37910a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
37920a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3793e860d2c9SBen Seri 	void *endptr = data + size;
37940a708f8fSGustavo F. Padovan 	int type, olen;
37950a708f8fSGustavo F. Padovan 	unsigned long val;
379636e999a8SMat Martineau 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
379766af7aafSAndrei Emeltchenko 	struct l2cap_conf_efs efs;
37980a708f8fSGustavo F. Padovan 
3799fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
38000a708f8fSGustavo F. Padovan 
38010a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
38020a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
38037c9cbd0bSMarcel Holtmann 		if (len < 0)
38047c9cbd0bSMarcel Holtmann 			break;
38050a708f8fSGustavo F. Padovan 
38060a708f8fSGustavo F. Padovan 		switch (type) {
38070a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3808af3d5d1cSMarcel Holtmann 			if (olen != 2)
3809af3d5d1cSMarcel Holtmann 				break;
38100a708f8fSGustavo F. Padovan 			if (val < L2CAP_DEFAULT_MIN_MTU) {
38110a708f8fSGustavo F. Padovan 				*result = L2CAP_CONF_UNACCEPT;
38120c1bc5c6SGustavo F. Padovan 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
38130a708f8fSGustavo F. Padovan 			} else
38140c1bc5c6SGustavo F. Padovan 				chan->imtu = val;
3815af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
3816af3d5d1cSMarcel Holtmann 					   endptr - ptr);
38170a708f8fSGustavo F. Padovan 			break;
38180a708f8fSGustavo F. Padovan 
38190a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3820af3d5d1cSMarcel Holtmann 			if (olen != 2)
3821af3d5d1cSMarcel Holtmann 				break;
38220c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
3823af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2,
3824af3d5d1cSMarcel Holtmann 					   chan->flush_to, endptr - ptr);
38250a708f8fSGustavo F. Padovan 			break;
38260a708f8fSGustavo F. Padovan 
38270a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3828af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3829af3d5d1cSMarcel Holtmann 				break;
38300a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
3831c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
38320c1bc5c6SGustavo F. Padovan 			    rfc.mode != chan->mode)
38330a708f8fSGustavo F. Padovan 				return -ECONNREFUSED;
383447d1ec61SGustavo F. Padovan 			chan->fcs = 0;
3835af3d5d1cSMarcel Holtmann 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3836af3d5d1cSMarcel Holtmann 					   (unsigned long) &rfc, endptr - ptr);
38370a708f8fSGustavo F. Padovan 			break;
38386327eb98SAndrei Emeltchenko 
38396327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3840af3d5d1cSMarcel Holtmann 			if (olen != 2)
3841af3d5d1cSMarcel Holtmann 				break;
3842c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, val, chan->ack_win);
38433e6b3b95SGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3844e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
38456327eb98SAndrei Emeltchenko 			break;
384666af7aafSAndrei Emeltchenko 
384766af7aafSAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3848af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3849af3d5d1cSMarcel Holtmann 				break;
385066af7aafSAndrei Emeltchenko 			memcpy(&efs, (void *)val, olen);
385166af7aafSAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
385266af7aafSAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
385366af7aafSAndrei Emeltchenko 			    efs.stype != chan->local_stype)
385466af7aafSAndrei Emeltchenko 				return -ECONNREFUSED;
38552d792818SGustavo Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3856e860d2c9SBen Seri 					   (unsigned long) &efs, endptr - ptr);
385766af7aafSAndrei Emeltchenko 			break;
3858cbabee78SAndrei Emeltchenko 
3859cbabee78SAndrei Emeltchenko 		case L2CAP_CONF_FCS:
3860af3d5d1cSMarcel Holtmann 			if (olen != 1)
3861af3d5d1cSMarcel Holtmann 				break;
3862cbabee78SAndrei Emeltchenko 			if (*result == L2CAP_CONF_PENDING)
3863cbabee78SAndrei Emeltchenko 				if (val == L2CAP_FCS_NONE)
3864f2592d3eSAndrei Emeltchenko 					set_bit(CONF_RECV_NO_FCS,
3865cbabee78SAndrei Emeltchenko 						&chan->conf_state);
3866cbabee78SAndrei Emeltchenko 			break;
38670a708f8fSGustavo F. Padovan 		}
38680a708f8fSGustavo F. Padovan 	}
38690a708f8fSGustavo F. Padovan 
38700c1bc5c6SGustavo F. Padovan 	if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
38710a708f8fSGustavo F. Padovan 		return -ECONNREFUSED;
38720a708f8fSGustavo F. Padovan 
38730c1bc5c6SGustavo F. Padovan 	chan->mode = rfc.mode;
38740a708f8fSGustavo F. Padovan 
38750e8b207eSAndrei Emeltchenko 	if (*result == L2CAP_CONF_SUCCESS || *result == L2CAP_CONF_PENDING) {
38760a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
38770a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
387847d1ec61SGustavo F. Padovan 			chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
387947d1ec61SGustavo F. Padovan 			chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
388047d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
3881c20f8e35SMat Martineau 			if (!test_bit(FLAG_EXT_CTRL, &chan->flags))
3882c20f8e35SMat Martineau 				chan->ack_win = min_t(u16, chan->ack_win,
3883c20f8e35SMat Martineau 						      rfc.txwin_size);
388466af7aafSAndrei Emeltchenko 
388566af7aafSAndrei Emeltchenko 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
388666af7aafSAndrei Emeltchenko 				chan->local_msdu = le16_to_cpu(efs.msdu);
388766af7aafSAndrei Emeltchenko 				chan->local_sdu_itime =
388866af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.sdu_itime);
388966af7aafSAndrei Emeltchenko 				chan->local_acc_lat = le32_to_cpu(efs.acc_lat);
389066af7aafSAndrei Emeltchenko 				chan->local_flush_to =
389166af7aafSAndrei Emeltchenko 					le32_to_cpu(efs.flush_to);
389266af7aafSAndrei Emeltchenko 			}
38930a708f8fSGustavo F. Padovan 			break;
389466af7aafSAndrei Emeltchenko 
38950a708f8fSGustavo F. Padovan 		case L2CAP_MODE_STREAMING:
389647d1ec61SGustavo F. Padovan 			chan->mps    = le16_to_cpu(rfc.max_pdu_size);
38970a708f8fSGustavo F. Padovan 		}
38980a708f8fSGustavo F. Padovan 	}
38990a708f8fSGustavo F. Padovan 
3900fe4128e0SGustavo F. Padovan 	req->dcid   = cpu_to_le16(chan->dcid);
3901dcf4adbfSJoe Perches 	req->flags  = cpu_to_le16(0);
39020a708f8fSGustavo F. Padovan 
39030a708f8fSGustavo F. Padovan 	return ptr - data;
39040a708f8fSGustavo F. Padovan }
39050a708f8fSGustavo F. Padovan 
39062d792818SGustavo Padovan static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
39072d792818SGustavo Padovan 				u16 result, u16 flags)
39080a708f8fSGustavo F. Padovan {
39090a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
39100a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
39110a708f8fSGustavo F. Padovan 
3912fe4128e0SGustavo F. Padovan 	BT_DBG("chan %p", chan);
39130a708f8fSGustavo F. Padovan 
3914fe4128e0SGustavo F. Padovan 	rsp->scid   = cpu_to_le16(chan->dcid);
39150a708f8fSGustavo F. Padovan 	rsp->result = cpu_to_le16(result);
39160a708f8fSGustavo F. Padovan 	rsp->flags  = cpu_to_le16(flags);
39170a708f8fSGustavo F. Padovan 
39180a708f8fSGustavo F. Padovan 	return ptr - data;
39190a708f8fSGustavo F. Padovan }
39200a708f8fSGustavo F. Padovan 
392127e2d4c8SJohan Hedberg void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
392227e2d4c8SJohan Hedberg {
392327e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
392427e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
392527e2d4c8SJohan Hedberg 
392627e2d4c8SJohan Hedberg 	BT_DBG("chan %p", chan);
392727e2d4c8SJohan Hedberg 
392827e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
392927e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
39303916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
39310cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
3932571f7390SMallikarjun Phulari 	rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
393327e2d4c8SJohan Hedberg 
393427e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
393527e2d4c8SJohan Hedberg 		       &rsp);
393627e2d4c8SJohan Hedberg }
393727e2d4c8SJohan Hedberg 
393815f02b91SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
393915f02b91SLuiz Augusto von Dentz {
394015f02b91SLuiz Augusto von Dentz 	struct {
394115f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
394215f02b91SLuiz Augusto von Dentz 		__le16 dcid[5];
394315f02b91SLuiz Augusto von Dentz 	} __packed pdu;
394415f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
394515f02b91SLuiz Augusto von Dentz 	u16 ident = chan->ident;
394615f02b91SLuiz Augusto von Dentz 	int i = 0;
394715f02b91SLuiz Augusto von Dentz 
394815f02b91SLuiz Augusto von Dentz 	if (!ident)
394915f02b91SLuiz Augusto von Dentz 		return;
395015f02b91SLuiz Augusto von Dentz 
395115f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p ident %d", chan, ident);
395215f02b91SLuiz Augusto von Dentz 
395315f02b91SLuiz Augusto von Dentz 	pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
395415f02b91SLuiz Augusto von Dentz 	pdu.rsp.mps     = cpu_to_le16(chan->mps);
395515f02b91SLuiz Augusto von Dentz 	pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
395615f02b91SLuiz Augusto von Dentz 	pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
395715f02b91SLuiz Augusto von Dentz 
395815f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
395915f02b91SLuiz Augusto von Dentz 
396015f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
396115f02b91SLuiz Augusto von Dentz 		if (chan->ident != ident)
396215f02b91SLuiz Augusto von Dentz 			continue;
396315f02b91SLuiz Augusto von Dentz 
396415f02b91SLuiz Augusto von Dentz 		/* Reset ident so only one response is sent */
396515f02b91SLuiz Augusto von Dentz 		chan->ident = 0;
396615f02b91SLuiz Augusto von Dentz 
396715f02b91SLuiz Augusto von Dentz 		/* Include all channels pending with the same ident */
396815f02b91SLuiz Augusto von Dentz 		pdu.dcid[i++] = cpu_to_le16(chan->scid);
396915f02b91SLuiz Augusto von Dentz 	}
397015f02b91SLuiz Augusto von Dentz 
397115f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
397215f02b91SLuiz Augusto von Dentz 
397315f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
397415f02b91SLuiz Augusto von Dentz 			sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
397515f02b91SLuiz Augusto von Dentz }
397615f02b91SLuiz Augusto von Dentz 
39778c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
3978710f9b0aSGustavo F. Padovan {
3979710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
39808c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
3981710f9b0aSGustavo F. Padovan 	u8 buf[128];
3982439f34acSAndrei Emeltchenko 	u8 rsp_code;
3983710f9b0aSGustavo F. Padovan 
3984fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
3985fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
3986dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
3987dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
3988439f34acSAndrei Emeltchenko 
3989439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
3990439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
3991439f34acSAndrei Emeltchenko 	else
3992439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
3993439f34acSAndrei Emeltchenko 
3994439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
3995439f34acSAndrei Emeltchenko 
3996439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
3997710f9b0aSGustavo F. Padovan 
3998c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
3999710f9b0aSGustavo F. Padovan 		return;
4000710f9b0aSGustavo F. Padovan 
4001710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4002e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
4003710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
4004710f9b0aSGustavo F. Padovan }
4005710f9b0aSGustavo F. Padovan 
400647d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
40070a708f8fSGustavo F. Padovan {
40080a708f8fSGustavo F. Padovan 	int type, olen;
40090a708f8fSGustavo F. Padovan 	unsigned long val;
4010c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
4011c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
4012c20f8e35SMat Martineau 	 */
4013c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
4014c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
4015c20f8e35SMat Martineau 		.mode = chan->mode,
4016dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
4017dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
4018c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
4019c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
4020c20f8e35SMat Martineau 	};
40210a708f8fSGustavo F. Padovan 
402247d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
40230a708f8fSGustavo F. Padovan 
40240c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
40250a708f8fSGustavo F. Padovan 		return;
40260a708f8fSGustavo F. Padovan 
40270a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
40280a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
40297c9cbd0bSMarcel Holtmann 		if (len < 0)
40307c9cbd0bSMarcel Holtmann 			break;
40310a708f8fSGustavo F. Padovan 
4032c20f8e35SMat Martineau 		switch (type) {
4033c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
4034af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
4035af3d5d1cSMarcel Holtmann 				break;
40360a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
4037c20f8e35SMat Martineau 			break;
4038c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
4039af3d5d1cSMarcel Holtmann 			if (olen != 2)
4040af3d5d1cSMarcel Holtmann 				break;
4041c20f8e35SMat Martineau 			txwin_ext = val;
4042c20f8e35SMat Martineau 			break;
4043c20f8e35SMat Martineau 		}
40440a708f8fSGustavo F. Padovan 	}
40450a708f8fSGustavo F. Padovan 
40460a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
40470a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
404847d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
404947d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
405047d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
4051c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4052c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
4053c20f8e35SMat Martineau 		else
4054c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
4055c20f8e35SMat Martineau 					      rfc.txwin_size);
40560a708f8fSGustavo F. Padovan 		break;
40570a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
405847d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
40590a708f8fSGustavo F. Padovan 	}
40600a708f8fSGustavo F. Padovan }
40610a708f8fSGustavo F. Padovan 
40622d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
4063cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4064cb3b3152SJohan Hedberg 				    u8 *data)
40650a708f8fSGustavo F. Padovan {
4066e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
40670a708f8fSGustavo F. Padovan 
4068cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
4069cb3b3152SJohan Hedberg 		return -EPROTO;
4070cb3b3152SJohan Hedberg 
4071e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
40720a708f8fSGustavo F. Padovan 		return 0;
40730a708f8fSGustavo F. Padovan 
40740a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
40750a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
407617cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
40770a708f8fSGustavo F. Padovan 
40780a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
40790a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
40800a708f8fSGustavo F. Padovan 
40810a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
40820a708f8fSGustavo F. Padovan 	}
40830a708f8fSGustavo F. Padovan 
40840a708f8fSGustavo F. Padovan 	return 0;
40850a708f8fSGustavo F. Padovan }
40860a708f8fSGustavo F. Padovan 
40871700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
40881700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
40894c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
40900a708f8fSGustavo F. Padovan {
40910a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
40920a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
409323691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
40940a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
40950a708f8fSGustavo F. Padovan 
40960a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
40970a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
40980a708f8fSGustavo F. Padovan 
4099097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
41000a708f8fSGustavo F. Padovan 
41010a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
41026f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
4103bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
410423691d75SGustavo F. Padovan 	if (!pchan) {
41050a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
41060a708f8fSGustavo F. Padovan 		goto sendresp;
41070a708f8fSGustavo F. Padovan 	}
41080a708f8fSGustavo F. Padovan 
41093df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41108ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
41110a708f8fSGustavo F. Padovan 
41120a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
4113dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
41140a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
41159f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
41160a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
41170a708f8fSGustavo F. Padovan 		goto response;
41180a708f8fSGustavo F. Padovan 	}
41190a708f8fSGustavo F. Padovan 
41200a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
41210a708f8fSGustavo F. Padovan 
4122dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
4123dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
4124dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
41252dfa1003SGustavo Padovan 		goto response;
4126dd1a8f8aSMallikarjun Phulari 	}
4127dd1a8f8aSMallikarjun Phulari 
4128dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
4129dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
4130dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
4131dd1a8f8aSMallikarjun Phulari 		goto response;
4132dd1a8f8aSMallikarjun Phulari 	}
41332dfa1003SGustavo Padovan 
413480b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
413580808e43SGustavo F. Padovan 	if (!chan)
41360a708f8fSGustavo F. Padovan 		goto response;
41370a708f8fSGustavo F. Padovan 
4138330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
4139330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
4140330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
4141330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
4142330b6c15SSyam Sidhardhan 	 */
4143330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
4144330b6c15SSyam Sidhardhan 
41457eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
41467eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
4147a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
4148a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
4149fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
4150fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
41511700915fSMat Martineau 	chan->local_amp_id = amp_id;
41520a708f8fSGustavo F. Padovan 
41536be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
415448454079SGustavo F. Padovan 
4155fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
41560a708f8fSGustavo F. Padovan 
41578d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
41580a708f8fSGustavo F. Padovan 
4159fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
41600a708f8fSGustavo F. Padovan 
41610a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4162e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
4163bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4164f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
41650a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
41660a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
41672dc4e510SGustavo Padovan 				chan->ops->defer(chan);
41680a708f8fSGustavo F. Padovan 			} else {
41691700915fSMat Martineau 				/* Force pending result for AMP controllers.
41701700915fSMat Martineau 				 * The connection will succeed after the
41711700915fSMat Martineau 				 * physical link is up.
41721700915fSMat Martineau 				 */
41736ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4174f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
41750a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
41766ed971caSMarcel Holtmann 				} else {
4177f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
41786ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
41791700915fSMat Martineau 				}
41800a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
41810a708f8fSGustavo F. Padovan 			}
41820a708f8fSGustavo F. Padovan 		} else {
4183f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
41840a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
41850a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
41860a708f8fSGustavo F. Padovan 		}
41870a708f8fSGustavo F. Padovan 	} else {
4188f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
41890a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
41900a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
41910a708f8fSGustavo F. Padovan 	}
41920a708f8fSGustavo F. Padovan 
41930a708f8fSGustavo F. Padovan response:
41948ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
41953df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4196a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
41970a708f8fSGustavo F. Padovan 
41980a708f8fSGustavo F. Padovan sendresp:
41990a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
42000a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
42010a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
42020a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
42034c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
42040a708f8fSGustavo F. Padovan 
42050a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
42060a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4207dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
42080a708f8fSGustavo F. Padovan 
42090a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
42100a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
42110a708f8fSGustavo F. Padovan 
4212ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
42130a708f8fSGustavo F. Padovan 
42142d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
42152d792818SGustavo Padovan 			       sizeof(info), &info);
42160a708f8fSGustavo F. Padovan 	}
42170a708f8fSGustavo F. Padovan 
4218c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
42190a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
42200a708f8fSGustavo F. Padovan 		u8 buf[128];
4221c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
42220a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4223e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
422473ffa904SGustavo F. Padovan 		chan->num_conf_req++;
42250a708f8fSGustavo F. Padovan 	}
42261700915fSMat Martineau 
42271700915fSMat Martineau 	return chan;
42284c89b6aaSMat Martineau }
42290a708f8fSGustavo F. Padovan 
42304c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4231cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
42324c89b6aaSMat Martineau {
42337b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
42347b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
42357b064edaSJaganath Kanakkassery 
4236cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4237cb3b3152SJohan Hedberg 		return -EPROTO;
4238cb3b3152SJohan Hedberg 
42397b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
4240d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
42417b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
424248ec92faSAlfonso Acosta 		mgmt_device_connected(hdev, hcon, 0, NULL, 0);
42437b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
42447b064edaSJaganath Kanakkassery 
4245300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
42460a708f8fSGustavo F. Padovan 	return 0;
42470a708f8fSGustavo F. Padovan }
42480a708f8fSGustavo F. Padovan 
42495909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4250cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4251cb3b3152SJohan Hedberg 				    u8 *data)
42520a708f8fSGustavo F. Padovan {
42530a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
42540a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
425548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42560a708f8fSGustavo F. Padovan 	u8 req[128];
42573df91ea2SAndrei Emeltchenko 	int err;
42580a708f8fSGustavo F. Padovan 
4259cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4260cb3b3152SJohan Hedberg 		return -EPROTO;
4261cb3b3152SJohan Hedberg 
42620a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
42630a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
42640a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
42650a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
42660a708f8fSGustavo F. Padovan 
42671b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
42681b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
42690a708f8fSGustavo F. Padovan 
42703df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
42713df91ea2SAndrei Emeltchenko 
42720a708f8fSGustavo F. Padovan 	if (scid) {
42733df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
42743df91ea2SAndrei Emeltchenko 		if (!chan) {
427521870b52SJohan Hedberg 			err = -EBADSLT;
42763df91ea2SAndrei Emeltchenko 			goto unlock;
42773df91ea2SAndrei Emeltchenko 		}
42780a708f8fSGustavo F. Padovan 	} else {
42793df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
42803df91ea2SAndrei Emeltchenko 		if (!chan) {
428121870b52SJohan Hedberg 			err = -EBADSLT;
42823df91ea2SAndrei Emeltchenko 			goto unlock;
42833df91ea2SAndrei Emeltchenko 		}
42840a708f8fSGustavo F. Padovan 	}
42850a708f8fSGustavo F. Padovan 
42863df91ea2SAndrei Emeltchenko 	err = 0;
42873df91ea2SAndrei Emeltchenko 
42886be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
428948454079SGustavo F. Padovan 
42900a708f8fSGustavo F. Padovan 	switch (result) {
42910a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
429289bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4293fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4294fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4295c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
42960a708f8fSGustavo F. Padovan 
4297c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
42980a708f8fSGustavo F. Padovan 			break;
42990a708f8fSGustavo F. Padovan 
43000a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4301e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
430273ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43030a708f8fSGustavo F. Padovan 		break;
43040a708f8fSGustavo F. Padovan 
43050a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4306c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
43070a708f8fSGustavo F. Padovan 		break;
43080a708f8fSGustavo F. Padovan 
43090a708f8fSGustavo F. Padovan 	default:
431048454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
43110a708f8fSGustavo F. Padovan 		break;
43120a708f8fSGustavo F. Padovan 	}
43130a708f8fSGustavo F. Padovan 
43146be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
43153df91ea2SAndrei Emeltchenko 
43163df91ea2SAndrei Emeltchenko unlock:
43173df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43183df91ea2SAndrei Emeltchenko 
43193df91ea2SAndrei Emeltchenko 	return err;
43200a708f8fSGustavo F. Padovan }
43210a708f8fSGustavo F. Padovan 
432247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
43230a708f8fSGustavo F. Padovan {
43240a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
43250a708f8fSGustavo F. Padovan 	 * sides request it.
43260a708f8fSGustavo F. Padovan 	 */
43270c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
432847d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4329f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
433047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
43310a708f8fSGustavo F. Padovan }
43320a708f8fSGustavo F. Padovan 
433329d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
433429d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
433529d8a590SAndrei Emeltchenko {
433629d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
433729d8a590SAndrei Emeltchenko 
433829d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
433929d8a590SAndrei Emeltchenko 	       flags);
434029d8a590SAndrei Emeltchenko 
434129d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
434229d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
434329d8a590SAndrei Emeltchenko 
434429d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
434529d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
434629d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
434729d8a590SAndrei Emeltchenko }
434829d8a590SAndrei Emeltchenko 
4349662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4350662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4351662d652dSJohan Hedberg {
4352662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4353662d652dSJohan Hedberg 
4354dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4355662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4356662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4357662d652dSJohan Hedberg 
4358662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4359662d652dSJohan Hedberg }
4360662d652dSJohan Hedberg 
43612d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
43622d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
43632d792818SGustavo Padovan 				   u8 *data)
43640a708f8fSGustavo F. Padovan {
43650a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
43660a708f8fSGustavo F. Padovan 	u16 dcid, flags;
43670a708f8fSGustavo F. Padovan 	u8 rsp[64];
436848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
43693c588192SMat Martineau 	int len, err = 0;
43700a708f8fSGustavo F. Padovan 
4371cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4372cb3b3152SJohan Hedberg 		return -EPROTO;
4373cb3b3152SJohan Hedberg 
43740a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
43750a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
43760a708f8fSGustavo F. Padovan 
43770a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
43780a708f8fSGustavo F. Padovan 
4379baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4380662d652dSJohan Hedberg 	if (!chan) {
4381662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4382662d652dSJohan Hedberg 		return 0;
4383662d652dSJohan Hedberg 	}
43840a708f8fSGustavo F. Padovan 
438596298f64SHoward Chung 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
438696298f64SHoward Chung 	    chan->state != BT_CONNECTED) {
4387662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4388662d652dSJohan Hedberg 				       chan->dcid);
43890a708f8fSGustavo F. Padovan 		goto unlock;
43900a708f8fSGustavo F. Padovan 	}
43910a708f8fSGustavo F. Padovan 
43920a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
43930a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4394cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
43950a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4396fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
43970a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
43980a708f8fSGustavo F. Padovan 		goto unlock;
43990a708f8fSGustavo F. Padovan 	}
44000a708f8fSGustavo F. Padovan 
44010a708f8fSGustavo F. Padovan 	/* Store config. */
440273ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
440373ffa904SGustavo F. Padovan 	chan->conf_len += len;
44040a708f8fSGustavo F. Padovan 
440559e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
44060a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
44070a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4408fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
44095325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
44100a708f8fSGustavo F. Padovan 		goto unlock;
44110a708f8fSGustavo F. Padovan 	}
44120a708f8fSGustavo F. Padovan 
44130a708f8fSGustavo F. Padovan 	/* Complete config. */
4414e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
44150a708f8fSGustavo F. Padovan 	if (len < 0) {
44165e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
44170a708f8fSGustavo F. Padovan 		goto unlock;
44180a708f8fSGustavo F. Padovan 	}
44190a708f8fSGustavo F. Padovan 
44201500109bSMat Martineau 	chan->ident = cmd->ident;
44210a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
442273ffa904SGustavo F. Padovan 	chan->num_conf_rsp++;
44230a708f8fSGustavo F. Padovan 
44240a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
442573ffa904SGustavo F. Padovan 	chan->conf_len = 0;
44260a708f8fSGustavo F. Padovan 
4427c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
44280a708f8fSGustavo F. Padovan 		goto unlock;
44290a708f8fSGustavo F. Padovan 
4430c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
443147d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44320a708f8fSGustavo F. Padovan 
4433105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4434105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44353c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44360a708f8fSGustavo F. Padovan 
44373c588192SMat Martineau 		if (err < 0)
44385e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44393c588192SMat Martineau 		else
4440cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44413c588192SMat Martineau 
44420a708f8fSGustavo F. Padovan 		goto unlock;
44430a708f8fSGustavo F. Padovan 	}
44440a708f8fSGustavo F. Padovan 
4445c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
44460a708f8fSGustavo F. Padovan 		u8 buf[64];
44470a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4448e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
444973ffa904SGustavo F. Padovan 		chan->num_conf_req++;
44500a708f8fSGustavo F. Padovan 	}
44510a708f8fSGustavo F. Padovan 
445249c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
44530e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
44540e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
44550e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
44560e8b207eSAndrei Emeltchenko 
44570e8b207eSAndrei Emeltchenko 		/* check compatibility */
44580e8b207eSAndrei Emeltchenko 
445979de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4460f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
446129d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
446279de886dSAndrei Emeltchenko 		else
446379de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
44640e8b207eSAndrei Emeltchenko 	}
44650e8b207eSAndrei Emeltchenko 
44660a708f8fSGustavo F. Padovan unlock:
44676be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
44683c588192SMat Martineau 	return err;
44690a708f8fSGustavo F. Padovan }
44700a708f8fSGustavo F. Padovan 
44712d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4472cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4473cb3b3152SJohan Hedberg 				   u8 *data)
44740a708f8fSGustavo F. Padovan {
44750a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
44760a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
447748454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4478cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
44793c588192SMat Martineau 	int err = 0;
44800a708f8fSGustavo F. Padovan 
4481cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4482cb3b3152SJohan Hedberg 		return -EPROTO;
4483cb3b3152SJohan Hedberg 
44840a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
44850a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
44860a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
44870a708f8fSGustavo F. Padovan 
448861386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
448961386cbaSAndrei Emeltchenko 	       result, len);
44900a708f8fSGustavo F. Padovan 
4491baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
449248454079SGustavo F. Padovan 	if (!chan)
44930a708f8fSGustavo F. Padovan 		return 0;
44940a708f8fSGustavo F. Padovan 
44950a708f8fSGustavo F. Padovan 	switch (result) {
44960a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
449747d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
44980e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
44990a708f8fSGustavo F. Padovan 		break;
45000a708f8fSGustavo F. Padovan 
45010e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
45020e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
45030e8b207eSAndrei Emeltchenko 
45040e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
45050e8b207eSAndrei Emeltchenko 			char buf[64];
45060e8b207eSAndrei Emeltchenko 
45070e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4508e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
45090e8b207eSAndrei Emeltchenko 			if (len < 0) {
45105e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45110e8b207eSAndrei Emeltchenko 				goto done;
45120e8b207eSAndrei Emeltchenko 			}
45130e8b207eSAndrei Emeltchenko 
4514f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
451579de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
451679de886dSAndrei Emeltchenko 							0);
45175ce66b59SAndrei Emeltchenko 			} else {
45185ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
45195ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
452079de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
45210e8b207eSAndrei Emeltchenko 				}
45225ce66b59SAndrei Emeltchenko 			}
45235ce66b59SAndrei Emeltchenko 		}
45240e8b207eSAndrei Emeltchenko 		goto done;
45250e8b207eSAndrei Emeltchenko 
452698d2c3e1SBastien Nocera 	case L2CAP_CONF_UNKNOWN:
45270a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
452873ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
45290a708f8fSGustavo F. Padovan 			char req[64];
45300a708f8fSGustavo F. Padovan 
45310a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
45325e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45330a708f8fSGustavo F. Padovan 				goto done;
45340a708f8fSGustavo F. Padovan 			}
45350a708f8fSGustavo F. Padovan 
45360a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
45370a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4538b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4539e860d2c9SBen Seri 						   req, sizeof(req), &result);
45400a708f8fSGustavo F. Padovan 			if (len < 0) {
45415e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45420a708f8fSGustavo F. Padovan 				goto done;
45430a708f8fSGustavo F. Padovan 			}
45440a708f8fSGustavo F. Padovan 
45450a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
45460a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
454773ffa904SGustavo F. Padovan 			chan->num_conf_req++;
45480a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
45490a708f8fSGustavo F. Padovan 				goto done;
45500a708f8fSGustavo F. Padovan 			break;
45510a708f8fSGustavo F. Padovan 		}
455219186c7bSGustavo A. R. Silva 		fallthrough;
45530a708f8fSGustavo F. Padovan 
45540a708f8fSGustavo F. Padovan 	default:
45556be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
45562e0052e4SAndrei Emeltchenko 
4557ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
45585e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
45590a708f8fSGustavo F. Padovan 		goto done;
45600a708f8fSGustavo F. Padovan 	}
45610a708f8fSGustavo F. Padovan 
456259e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
45630a708f8fSGustavo F. Padovan 		goto done;
45640a708f8fSGustavo F. Padovan 
4565c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
45660a708f8fSGustavo F. Padovan 
4567c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
456847d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
45690a708f8fSGustavo F. Padovan 
4570105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4571105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
45723c588192SMat Martineau 			err = l2cap_ertm_init(chan);
45730a708f8fSGustavo F. Padovan 
45743c588192SMat Martineau 		if (err < 0)
45755e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
45763c588192SMat Martineau 		else
4577cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
45780a708f8fSGustavo F. Padovan 	}
45790a708f8fSGustavo F. Padovan 
45800a708f8fSGustavo F. Padovan done:
45816be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
45823c588192SMat Martineau 	return err;
45830a708f8fSGustavo F. Padovan }
45840a708f8fSGustavo F. Padovan 
45852d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4586cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4587cb3b3152SJohan Hedberg 				       u8 *data)
45880a708f8fSGustavo F. Padovan {
45890a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
45900a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
45910a708f8fSGustavo F. Padovan 	u16 dcid, scid;
459248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
45930a708f8fSGustavo F. Padovan 
4594cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4595cb3b3152SJohan Hedberg 		return -EPROTO;
4596cb3b3152SJohan Hedberg 
45970a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
45980a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
45990a708f8fSGustavo F. Padovan 
46000a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
46010a708f8fSGustavo F. Padovan 
46023df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
46033df91ea2SAndrei Emeltchenko 
46043df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
46053df91ea2SAndrei Emeltchenko 	if (!chan) {
46063df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4607662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4608662d652dSJohan Hedberg 		return 0;
46093df91ea2SAndrei Emeltchenko 	}
46100a708f8fSGustavo F. Padovan 
46116c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
46126be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
46136be36555SAndrei Emeltchenko 
4614fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4615fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
46160a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
46170a708f8fSGustavo F. Padovan 
46185ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
46190a708f8fSGustavo F. Padovan 
462048454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
46216be36555SAndrei Emeltchenko 
462280b98027SGustavo Padovan 	chan->ops->close(chan);
46236c08fc89SManish Mandlik 
46246c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
462561d6ef3eSMat Martineau 	l2cap_chan_put(chan);
46263df91ea2SAndrei Emeltchenko 
46273df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46283df91ea2SAndrei Emeltchenko 
46290a708f8fSGustavo F. Padovan 	return 0;
46300a708f8fSGustavo F. Padovan }
46310a708f8fSGustavo F. Padovan 
46322d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4633cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4634cb3b3152SJohan Hedberg 				       u8 *data)
46350a708f8fSGustavo F. Padovan {
46360a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
46370a708f8fSGustavo F. Padovan 	u16 dcid, scid;
463848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
46390a708f8fSGustavo F. Padovan 
4640cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4641cb3b3152SJohan Hedberg 		return -EPROTO;
4642cb3b3152SJohan Hedberg 
46430a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
46440a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
46450a708f8fSGustavo F. Padovan 
46460a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
46470a708f8fSGustavo F. Padovan 
46483df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
46493df91ea2SAndrei Emeltchenko 
46503df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
46513df91ea2SAndrei Emeltchenko 	if (!chan) {
46523df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
46530a708f8fSGustavo F. Padovan 		return 0;
46543df91ea2SAndrei Emeltchenko 	}
46550a708f8fSGustavo F. Padovan 
46566c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
46576be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
465848454079SGustavo F. Padovan 
465928261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
466028261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
46616c08fc89SManish Mandlik 		l2cap_chan_put(chan);
466228261da8SMatias Karhumaa 		mutex_unlock(&conn->chan_lock);
466328261da8SMatias Karhumaa 		return 0;
466428261da8SMatias Karhumaa 	}
466528261da8SMatias Karhumaa 
466648454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
46676be36555SAndrei Emeltchenko 
466880b98027SGustavo Padovan 	chan->ops->close(chan);
46696c08fc89SManish Mandlik 
46706c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
467161d6ef3eSMat Martineau 	l2cap_chan_put(chan);
46723df91ea2SAndrei Emeltchenko 
46733df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46743df91ea2SAndrei Emeltchenko 
46750a708f8fSGustavo F. Padovan 	return 0;
46760a708f8fSGustavo F. Padovan }
46770a708f8fSGustavo F. Padovan 
46782d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4679cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4680cb3b3152SJohan Hedberg 					u8 *data)
46810a708f8fSGustavo F. Padovan {
46820a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
46830a708f8fSGustavo F. Padovan 	u16 type;
46840a708f8fSGustavo F. Padovan 
4685cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4686cb3b3152SJohan Hedberg 		return -EPROTO;
4687cb3b3152SJohan Hedberg 
46880a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
46890a708f8fSGustavo F. Padovan 
46900a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
46910a708f8fSGustavo F. Padovan 
46920a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
46930a708f8fSGustavo F. Padovan 		u8 buf[8];
46940a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
46950a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4696dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4697dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
46980a708f8fSGustavo F. Padovan 		if (!disable_ertm)
46990a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
47000a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
47010bd49fc7SJohan Hedberg 		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
47026327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
47036327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4704a5fd6f30SAndrei Emeltchenko 
47050a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
47062d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47072d792818SGustavo Padovan 			       buf);
47080a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
47090a708f8fSGustavo F. Padovan 		u8 buf[12];
47100a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
471150a147cdSMat Martineau 
4712dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4713dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
47140bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
47150bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
47162d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47172d792818SGustavo Padovan 			       buf);
47180a708f8fSGustavo F. Padovan 	} else {
47190a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
47200a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4721dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
47222d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
47232d792818SGustavo Padovan 			       &rsp);
47240a708f8fSGustavo F. Padovan 	}
47250a708f8fSGustavo F. Padovan 
47260a708f8fSGustavo F. Padovan 	return 0;
47270a708f8fSGustavo F. Padovan }
47280a708f8fSGustavo F. Padovan 
47292d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4730cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4731cb3b3152SJohan Hedberg 					u8 *data)
47320a708f8fSGustavo F. Padovan {
47330a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
47340a708f8fSGustavo F. Padovan 	u16 type, result;
47350a708f8fSGustavo F. Padovan 
47363f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4737cb3b3152SJohan Hedberg 		return -EPROTO;
4738cb3b3152SJohan Hedberg 
47390a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
47400a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
47410a708f8fSGustavo F. Padovan 
47420a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
47430a708f8fSGustavo F. Padovan 
4744e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4745e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4746e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4747e90165beSAndrei Emeltchenko 		return 0;
4748e90165beSAndrei Emeltchenko 
474917cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
47500a708f8fSGustavo F. Padovan 
47510a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
47520a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47530a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
47540a708f8fSGustavo F. Padovan 
47550a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
47560a708f8fSGustavo F. Padovan 
47570a708f8fSGustavo F. Padovan 		return 0;
47580a708f8fSGustavo F. Padovan 	}
47590a708f8fSGustavo F. Padovan 
4760978c93b9SAndrei Emeltchenko 	switch (type) {
4761978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
47620a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
47630a708f8fSGustavo F. Padovan 
47640a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
47650a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4766dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
47670a708f8fSGustavo F. Padovan 
47680a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
47690a708f8fSGustavo F. Padovan 
47700a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
47710a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
47720a708f8fSGustavo F. Padovan 		} else {
47730a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47740a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
47750a708f8fSGustavo F. Padovan 
47760a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
47770a708f8fSGustavo F. Padovan 		}
4778978c93b9SAndrei Emeltchenko 		break;
4779978c93b9SAndrei Emeltchenko 
4780978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
47810bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
47820a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
47830a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
47840a708f8fSGustavo F. Padovan 
47850a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4786978c93b9SAndrei Emeltchenko 		break;
47870a708f8fSGustavo F. Padovan 	}
47880a708f8fSGustavo F. Padovan 
47890a708f8fSGustavo F. Padovan 	return 0;
47900a708f8fSGustavo F. Padovan }
47910a708f8fSGustavo F. Padovan 
47921700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
47932d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
47942d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4795f94ff6ffSMat Martineau {
4796f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
47976e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
47981700915fSMat Martineau 	struct l2cap_chan *chan;
47996e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4800f94ff6ffSMat Martineau 	u16 psm, scid;
4801f94ff6ffSMat Martineau 
4802f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4803f94ff6ffSMat Martineau 		return -EPROTO;
4804f94ff6ffSMat Martineau 
48050bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4806f94ff6ffSMat Martineau 		return -EINVAL;
4807f94ff6ffSMat Martineau 
4808f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4809f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4810f94ff6ffSMat Martineau 
4811ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4812f94ff6ffSMat Martineau 
48136e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
48146ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
48156e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48166e1df6a6SAndrei Emeltchenko 			      req->amp_id);
48176e1df6a6SAndrei Emeltchenko 		return 0;
48186e1df6a6SAndrei Emeltchenko 	}
48191700915fSMat Martineau 
48201700915fSMat Martineau 	/* Validate AMP controller id */
48211700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
48226e1df6a6SAndrei Emeltchenko 	if (!hdev)
48236e1df6a6SAndrei Emeltchenko 		goto error;
48241700915fSMat Martineau 
48256e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
48266e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
48276e1df6a6SAndrei Emeltchenko 		goto error;
48286e1df6a6SAndrei Emeltchenko 	}
48296e1df6a6SAndrei Emeltchenko 
48306e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48316e1df6a6SAndrei Emeltchenko 			     req->amp_id);
48326e1df6a6SAndrei Emeltchenko 	if (chan) {
48336e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
48346e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
48356e1df6a6SAndrei Emeltchenko 
483698e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
483798e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
48386e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
48396e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4840662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4841662d652dSJohan Hedberg 					       chan->dcid);
4842662d652dSJohan Hedberg 			return 0;
48436e1df6a6SAndrei Emeltchenko 		}
48446e1df6a6SAndrei Emeltchenko 
48456e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
48466e1df6a6SAndrei Emeltchenko 
48476e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
48486e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4849fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
48506e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
48516e1df6a6SAndrei Emeltchenko 	}
48526e1df6a6SAndrei Emeltchenko 
48536e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
48546e1df6a6SAndrei Emeltchenko 
48556e1df6a6SAndrei Emeltchenko 	return 0;
48566e1df6a6SAndrei Emeltchenko 
48576e1df6a6SAndrei Emeltchenko error:
4858f94ff6ffSMat Martineau 	rsp.dcid = 0;
4859f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
4860dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
4861dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4862f94ff6ffSMat Martineau 
4863f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4864f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4865f94ff6ffSMat Martineau 
4866dc280801SJohan Hedberg 	return 0;
4867f94ff6ffSMat Martineau }
4868f94ff6ffSMat Martineau 
48698eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
48708eb200bdSMat Martineau {
48718eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
48728eb200bdSMat Martineau 	u8 ident;
48738eb200bdSMat Martineau 
48748eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
48758eb200bdSMat Martineau 
48768eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
48778eb200bdSMat Martineau 	chan->ident = ident;
48788eb200bdSMat Martineau 
48798eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
48808eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
48818eb200bdSMat Martineau 
48828eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
48838eb200bdSMat Martineau 		       &req);
48848eb200bdSMat Martineau 
48858eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
48868eb200bdSMat Martineau }
48878eb200bdSMat Martineau 
48881500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
48898d5a04a1SMat Martineau {
48908d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
48918d5a04a1SMat Martineau 
48921500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
48938d5a04a1SMat Martineau 
48941500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
48958d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
48968d5a04a1SMat Martineau 
48971500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
48981500109bSMat Martineau 		       sizeof(rsp), &rsp);
48998d5a04a1SMat Martineau }
49008d5a04a1SMat Martineau 
49015b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
49028d5a04a1SMat Martineau {
49038d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49048d5a04a1SMat Martineau 
49055b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
49068d5a04a1SMat Martineau 
49075b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
49088d5a04a1SMat Martineau 
49095b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
49108d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
49118d5a04a1SMat Martineau 
49125b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
49135b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49145b155ef9SMat Martineau 
49155b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
49165b155ef9SMat Martineau }
49175b155ef9SMat Martineau 
49185b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
49195b155ef9SMat Martineau {
49205b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49215b155ef9SMat Martineau 
49225b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
49235b155ef9SMat Martineau 
49245b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
4925dcf4adbfSJoe Perches 	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
49265b155ef9SMat Martineau 
49275b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
49285b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49298d5a04a1SMat Martineau }
49308d5a04a1SMat Martineau 
49318d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
49328d5a04a1SMat Martineau 					 u16 icid)
49338d5a04a1SMat Martineau {
49348d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
49358d5a04a1SMat Martineau 
4936ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
49378d5a04a1SMat Martineau 
49388d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
49398d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
49408d5a04a1SMat Martineau }
49418d5a04a1SMat Martineau 
49425f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
49435f3847a4SMat Martineau {
49445f3847a4SMat Martineau 	chan->hs_hchan = NULL;
49455f3847a4SMat Martineau 	chan->hs_hcon = NULL;
49465f3847a4SMat Martineau 
49475f3847a4SMat Martineau 	/* Placeholder - release the logical link */
49485f3847a4SMat Martineau }
49495f3847a4SMat Martineau 
49501500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
49511500109bSMat Martineau {
49521500109bSMat Martineau 	/* Logical link setup failed */
49531500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
49541500109bSMat Martineau 		/* Create channel failure, disconnect */
49555e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
49561500109bSMat Martineau 		return;
49571500109bSMat Martineau 	}
49581500109bSMat Martineau 
49591500109bSMat Martineau 	switch (chan->move_role) {
49601500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
49611500109bSMat Martineau 		l2cap_move_done(chan);
49621500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
49631500109bSMat Martineau 		break;
49641500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
49651500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
49661500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
49671500109bSMat Martineau 			/* Remote has only sent pending or
49681500109bSMat Martineau 			 * success responses, clean up
49691500109bSMat Martineau 			 */
49701500109bSMat Martineau 			l2cap_move_done(chan);
49711500109bSMat Martineau 		}
49721500109bSMat Martineau 
49731500109bSMat Martineau 		/* Other amp move states imply that the move
49741500109bSMat Martineau 		 * has already aborted
49751500109bSMat Martineau 		 */
49761500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
49771500109bSMat Martineau 		break;
49781500109bSMat Martineau 	}
49791500109bSMat Martineau }
49801500109bSMat Martineau 
49811500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
49821500109bSMat Martineau 					struct hci_chan *hchan)
49831500109bSMat Martineau {
49841500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
49851500109bSMat Martineau 
4986336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
49871500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
49881500109bSMat Martineau 
498935ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
49901500109bSMat Martineau 
49911500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
4992fe79c6feSAndrei Emeltchenko 		int err;
49931500109bSMat Martineau 
49941500109bSMat Martineau 		set_default_fcs(chan);
49951500109bSMat Martineau 
49961500109bSMat Martineau 		err = l2cap_ertm_init(chan);
49971500109bSMat Martineau 		if (err < 0)
49985e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
49991500109bSMat Martineau 		else
50001500109bSMat Martineau 			l2cap_chan_ready(chan);
50011500109bSMat Martineau 	}
50021500109bSMat Martineau }
50031500109bSMat Martineau 
50041500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
50051500109bSMat Martineau 				      struct hci_chan *hchan)
50061500109bSMat Martineau {
50071500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
50081500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
50091500109bSMat Martineau 
50101500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
50111500109bSMat Martineau 
50121500109bSMat Martineau 	switch (chan->move_state) {
50131500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50141500109bSMat Martineau 		/* Move confirm will be sent after a success
50151500109bSMat Martineau 		 * response is received
50161500109bSMat Martineau 		 */
50171500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50181500109bSMat Martineau 		break;
50191500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
50201500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
50211500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50221500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
50231500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50241500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50251500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50261500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
50271500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
50281500109bSMat Martineau 		}
50291500109bSMat Martineau 		break;
50301500109bSMat Martineau 	default:
50311500109bSMat Martineau 		/* Move was not in expected state, free the channel */
50321500109bSMat Martineau 		__release_logical_link(chan);
50331500109bSMat Martineau 
50341500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
50351500109bSMat Martineau 	}
50361500109bSMat Martineau }
50371500109bSMat Martineau 
50381500109bSMat Martineau /* Call with chan locked */
503927695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
50405b155ef9SMat Martineau 		       u8 status)
50415b155ef9SMat Martineau {
50421500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
50431500109bSMat Martineau 
50441500109bSMat Martineau 	if (status) {
50451500109bSMat Martineau 		l2cap_logical_fail(chan);
50461500109bSMat Martineau 		__release_logical_link(chan);
50475b155ef9SMat Martineau 		return;
50485b155ef9SMat Martineau 	}
50495b155ef9SMat Martineau 
50501500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
50511500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
50526ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
50531500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
50541500109bSMat Martineau 	} else {
50551500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
50561500109bSMat Martineau 	}
50571500109bSMat Martineau }
50581500109bSMat Martineau 
50593f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
50603f7a56c4SMat Martineau {
50613f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
50623f7a56c4SMat Martineau 
50636ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
50643f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
50653f7a56c4SMat Martineau 			return;
50663f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
50673f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
50683f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
50693f7a56c4SMat Martineau 	} else {
50703f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
50713f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50723f7a56c4SMat Martineau 		chan->move_id = 0;
50733f7a56c4SMat Martineau 		l2cap_move_setup(chan);
50743f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
50753f7a56c4SMat Martineau 	}
50763f7a56c4SMat Martineau }
50773f7a56c4SMat Martineau 
50788eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
50798eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
50808eb200bdSMat Martineau {
508162748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
508262748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
508362748ca1SAndrei Emeltchenko 
508412d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
508512d6cc60SAndrei Emeltchenko 
508662748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
508762748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
508862748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
508962748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
509062748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
509162748ca1SAndrei Emeltchenko 		} else {
509262748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
509362748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
509462748ca1SAndrei Emeltchenko 		}
509562748ca1SAndrei Emeltchenko 
509662748ca1SAndrei Emeltchenko 		return;
509762748ca1SAndrei Emeltchenko 	}
509862748ca1SAndrei Emeltchenko 
509962748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
510062748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
51018eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
51028eb200bdSMat Martineau 		char buf[128];
51038eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
51048eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
51058eb200bdSMat Martineau 
51068eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
51078eb200bdSMat Martineau 			/* Send successful response */
5108dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
5109dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51108eb200bdSMat Martineau 		} else {
51118eb200bdSMat Martineau 			/* Send negative response */
5112dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
5113dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51148eb200bdSMat Martineau 		}
51158eb200bdSMat Martineau 
51168eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
51178eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
51188eb200bdSMat Martineau 
51198eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
5120f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
51218eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
51228eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
51238eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
5124e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
51258eb200bdSMat Martineau 			chan->num_conf_req++;
51268eb200bdSMat Martineau 		}
51278eb200bdSMat Martineau 	}
51288eb200bdSMat Martineau }
51298eb200bdSMat Martineau 
51308eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
51318eb200bdSMat Martineau 				   u8 remote_amp_id)
51328eb200bdSMat Martineau {
51338eb200bdSMat Martineau 	l2cap_move_setup(chan);
51348eb200bdSMat Martineau 	chan->move_id = local_amp_id;
51358eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
51368eb200bdSMat Martineau 
51378eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
51388eb200bdSMat Martineau }
51398eb200bdSMat Martineau 
51408eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
51418eb200bdSMat Martineau {
51428eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
51438eb200bdSMat Martineau 
51448eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
51458eb200bdSMat Martineau 
51468eb200bdSMat Martineau 	if (hchan) {
51478eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
51488eb200bdSMat Martineau 			/* Logical link is ready to go */
51498eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
51508eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
51518eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
51528eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
51538eb200bdSMat Martineau 
51548eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
51558eb200bdSMat Martineau 		} else {
51568eb200bdSMat Martineau 			/* Wait for logical link to be ready */
51578eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
51588eb200bdSMat Martineau 		}
51598eb200bdSMat Martineau 	} else {
51608eb200bdSMat Martineau 		/* Logical link not available */
51618eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
51628eb200bdSMat Martineau 	}
51638eb200bdSMat Martineau }
51648eb200bdSMat Martineau 
51658eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
51668eb200bdSMat Martineau {
51678eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
51688eb200bdSMat Martineau 		u8 rsp_result;
51698eb200bdSMat Martineau 		if (result == -EINVAL)
51708eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
51718eb200bdSMat Martineau 		else
51728eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
51738eb200bdSMat Martineau 
51748eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
51758eb200bdSMat Martineau 	}
51768eb200bdSMat Martineau 
51778eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
51788eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
51798eb200bdSMat Martineau 
51808eb200bdSMat Martineau 	/* Restart data transmission */
51818eb200bdSMat Martineau 	l2cap_ertm_send(chan);
51828eb200bdSMat Martineau }
51838eb200bdSMat Martineau 
5184a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5185a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
51868eb200bdSMat Martineau {
5187770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5188fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5189770bfefaSAndrei Emeltchenko 
51908eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
51918eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
51928eb200bdSMat Martineau 
5193df66499aSDan Carpenter 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED)
51948eb200bdSMat Martineau 		return;
51958eb200bdSMat Martineau 
51968eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
51978eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
51988eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
51998eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
52008eb200bdSMat Martineau 	} else {
52018eb200bdSMat Martineau 		switch (chan->move_role) {
52028eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
52038eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
52048eb200bdSMat Martineau 					       remote_amp_id);
52058eb200bdSMat Martineau 			break;
52068eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
52078eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
52088eb200bdSMat Martineau 			break;
52098eb200bdSMat Martineau 		default:
52108eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
52118eb200bdSMat Martineau 			break;
52128eb200bdSMat Martineau 		}
52138eb200bdSMat Martineau 	}
52148eb200bdSMat Martineau }
52158eb200bdSMat Martineau 
52168d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5217ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5218ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
52198d5a04a1SMat Martineau {
52208d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
52211500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
522202b0fbb9SMat Martineau 	struct l2cap_chan *chan;
52238d5a04a1SMat Martineau 	u16 icid = 0;
52248d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
52258d5a04a1SMat Martineau 
52268d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
52278d5a04a1SMat Martineau 		return -EPROTO;
52288d5a04a1SMat Martineau 
52298d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
52308d5a04a1SMat Martineau 
5231ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
52328d5a04a1SMat Martineau 
52330bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
52348d5a04a1SMat Martineau 		return -EINVAL;
52358d5a04a1SMat Martineau 
523602b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
523702b0fbb9SMat Martineau 	if (!chan) {
52381500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
5239dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
52401500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
52411500109bSMat Martineau 			       sizeof(rsp), &rsp);
524202b0fbb9SMat Martineau 		return 0;
524302b0fbb9SMat Martineau 	}
524402b0fbb9SMat Martineau 
52451500109bSMat Martineau 	chan->ident = cmd->ident;
52461500109bSMat Martineau 
524702b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
524802b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
524902b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
525002b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
525102b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
525202b0fbb9SMat Martineau 		goto send_move_response;
525302b0fbb9SMat Martineau 	}
525402b0fbb9SMat Martineau 
525502b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
525602b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
525702b0fbb9SMat Martineau 		goto send_move_response;
525802b0fbb9SMat Martineau 	}
525902b0fbb9SMat Martineau 
52606ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
526102b0fbb9SMat Martineau 		struct hci_dev *hdev;
526202b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
526302b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
526402b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
526502b0fbb9SMat Martineau 			if (hdev)
526602b0fbb9SMat Martineau 				hci_dev_put(hdev);
526702b0fbb9SMat Martineau 
526802b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
526902b0fbb9SMat Martineau 			goto send_move_response;
527002b0fbb9SMat Martineau 		}
527102b0fbb9SMat Martineau 		hci_dev_put(hdev);
527202b0fbb9SMat Martineau 	}
527302b0fbb9SMat Martineau 
527402b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
527502b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
527602b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
527702b0fbb9SMat Martineau 	 */
527802b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
527902b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
52806f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
528102b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
528202b0fbb9SMat Martineau 		goto send_move_response;
528302b0fbb9SMat Martineau 	}
528402b0fbb9SMat Martineau 
528502b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
528602b0fbb9SMat Martineau 	l2cap_move_setup(chan);
528702b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
528802b0fbb9SMat Martineau 
52896ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
529002b0fbb9SMat Martineau 		/* Moving to BR/EDR */
529102b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
529202b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
529302b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
529402b0fbb9SMat Martineau 		} else {
529502b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
529602b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
529702b0fbb9SMat Martineau 		}
529802b0fbb9SMat Martineau 	} else {
529902b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
530002b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
530102b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
530202b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
530302b0fbb9SMat Martineau 	}
530402b0fbb9SMat Martineau 
530502b0fbb9SMat Martineau send_move_response:
53061500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
53078d5a04a1SMat Martineau 
530802b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
530902b0fbb9SMat Martineau 
53108d5a04a1SMat Martineau 	return 0;
53118d5a04a1SMat Martineau }
53128d5a04a1SMat Martineau 
53135b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
53145b155ef9SMat Martineau {
53155b155ef9SMat Martineau 	struct l2cap_chan *chan;
53165b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
53175b155ef9SMat Martineau 
53185b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53195b155ef9SMat Martineau 	if (!chan) {
53205b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
53215b155ef9SMat Martineau 		return;
53225b155ef9SMat Martineau 	}
53235b155ef9SMat Martineau 
53245b155ef9SMat Martineau 	__clear_chan_timer(chan);
53255b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
53265b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
53275b155ef9SMat Martineau 
53285b155ef9SMat Martineau 	switch (chan->move_state) {
53295b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
53305b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
53315b155ef9SMat Martineau 		 * is complete.
53325b155ef9SMat Martineau 		 */
53335b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
53345b155ef9SMat Martineau 		break;
53355b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
53365b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
53375b155ef9SMat Martineau 			break;
53385b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
53395b155ef9SMat Martineau 				    &chan->conn_state)) {
53405b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
53415b155ef9SMat Martineau 		} else {
53425b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
53435b155ef9SMat Martineau 			 * proceed with move
53445b155ef9SMat Martineau 			 */
53455b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
53465b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
53475b155ef9SMat Martineau 		}
53485b155ef9SMat Martineau 		break;
53495b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
53505b155ef9SMat Martineau 		/* Moving to AMP */
53515b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
53525b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
53535b155ef9SMat Martineau 			 * after logical link is ready
53545b155ef9SMat Martineau 			 */
53555b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
53565b155ef9SMat Martineau 		} else {
53575b155ef9SMat Martineau 			/* Both logical link and move success
53585b155ef9SMat Martineau 			 * are required to confirm
53595b155ef9SMat Martineau 			 */
53605b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
53615b155ef9SMat Martineau 		}
53625b155ef9SMat Martineau 
53635b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
53645b155ef9SMat Martineau 		if (!hchan) {
53655b155ef9SMat Martineau 			/* Logical link not available */
53665b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
53675b155ef9SMat Martineau 			break;
53685b155ef9SMat Martineau 		}
53695b155ef9SMat Martineau 
53705b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
53715b155ef9SMat Martineau 		 * send confirmation.
53725b155ef9SMat Martineau 		 */
53735b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
53745b155ef9SMat Martineau 			break;
53755b155ef9SMat Martineau 
53765b155ef9SMat Martineau 		/* Logical link is already ready to go */
53775b155ef9SMat Martineau 
53785b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
53795b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
53805b155ef9SMat Martineau 
53815b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
53825b155ef9SMat Martineau 			/* Can confirm now */
53835b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
53845b155ef9SMat Martineau 		} else {
53855b155ef9SMat Martineau 			/* Now only need move success
53865b155ef9SMat Martineau 			 * to confirm
53875b155ef9SMat Martineau 			 */
53885b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
53895b155ef9SMat Martineau 		}
53905b155ef9SMat Martineau 
53915b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
53925b155ef9SMat Martineau 		break;
53935b155ef9SMat Martineau 	default:
53945b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
53955b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
53965b155ef9SMat Martineau 		l2cap_move_done(chan);
53975b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
53985b155ef9SMat Martineau 	}
53995b155ef9SMat Martineau 
54005b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
54015b155ef9SMat Martineau }
54025b155ef9SMat Martineau 
54035b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
54045b155ef9SMat Martineau 			    u16 result)
54055b155ef9SMat Martineau {
54065b155ef9SMat Martineau 	struct l2cap_chan *chan;
54075b155ef9SMat Martineau 
54085b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
54095b155ef9SMat Martineau 	if (!chan) {
54105b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
54115b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
54125b155ef9SMat Martineau 		return;
54135b155ef9SMat Martineau 	}
54145b155ef9SMat Martineau 
54155b155ef9SMat Martineau 	__clear_chan_timer(chan);
54165b155ef9SMat Martineau 
54175b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
54185b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
54195b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
54205b155ef9SMat Martineau 		} else {
54215b155ef9SMat Martineau 			/* Cleanup - cancel move */
54225b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
54235b155ef9SMat Martineau 			l2cap_move_done(chan);
54245b155ef9SMat Martineau 		}
54255b155ef9SMat Martineau 	}
54265b155ef9SMat Martineau 
54275b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
54285b155ef9SMat Martineau 
54295b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
54305b155ef9SMat Martineau }
54315b155ef9SMat Martineau 
54325b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5433ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5434ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
54358d5a04a1SMat Martineau {
54368d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
54378d5a04a1SMat Martineau 	u16 icid, result;
54388d5a04a1SMat Martineau 
54398d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
54408d5a04a1SMat Martineau 		return -EPROTO;
54418d5a04a1SMat Martineau 
54428d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
54438d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
54448d5a04a1SMat Martineau 
5445ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
54468d5a04a1SMat Martineau 
54475b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
54485b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
54495b155ef9SMat Martineau 	else
54505b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
54518d5a04a1SMat Martineau 
54528d5a04a1SMat Martineau 	return 0;
54538d5a04a1SMat Martineau }
54548d5a04a1SMat Martineau 
54555f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5456ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5457ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
54588d5a04a1SMat Martineau {
54598d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
54605f3847a4SMat Martineau 	struct l2cap_chan *chan;
54618d5a04a1SMat Martineau 	u16 icid, result;
54628d5a04a1SMat Martineau 
54638d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
54648d5a04a1SMat Martineau 		return -EPROTO;
54658d5a04a1SMat Martineau 
54668d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
54678d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
54688d5a04a1SMat Martineau 
5469ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
54708d5a04a1SMat Martineau 
54715f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
54725f3847a4SMat Martineau 	if (!chan) {
54735f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
54748d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
54755f3847a4SMat Martineau 		return 0;
54765f3847a4SMat Martineau 	}
54775f3847a4SMat Martineau 
54785f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
54795f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
54805f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
54816ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
54825f3847a4SMat Martineau 				__release_logical_link(chan);
54835f3847a4SMat Martineau 		} else {
54845f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
54855f3847a4SMat Martineau 		}
54865f3847a4SMat Martineau 
54875f3847a4SMat Martineau 		l2cap_move_done(chan);
54885f3847a4SMat Martineau 	}
54895f3847a4SMat Martineau 
54905f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
54915f3847a4SMat Martineau 
54925f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
54938d5a04a1SMat Martineau 
54948d5a04a1SMat Martineau 	return 0;
54958d5a04a1SMat Martineau }
54968d5a04a1SMat Martineau 
54978d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5498ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5499ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
55008d5a04a1SMat Martineau {
55018d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
55023fd71a0aSMat Martineau 	struct l2cap_chan *chan;
55038d5a04a1SMat Martineau 	u16 icid;
55048d5a04a1SMat Martineau 
55058d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
55068d5a04a1SMat Martineau 		return -EPROTO;
55078d5a04a1SMat Martineau 
55088d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
55098d5a04a1SMat Martineau 
5510ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
55118d5a04a1SMat Martineau 
55123fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
55133fd71a0aSMat Martineau 	if (!chan)
55143fd71a0aSMat Martineau 		return 0;
55153fd71a0aSMat Martineau 
55163fd71a0aSMat Martineau 	__clear_chan_timer(chan);
55173fd71a0aSMat Martineau 
55183fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
55193fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
55203fd71a0aSMat Martineau 
55216ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
55223fd71a0aSMat Martineau 			__release_logical_link(chan);
55233fd71a0aSMat Martineau 
55243fd71a0aSMat Martineau 		l2cap_move_done(chan);
55253fd71a0aSMat Martineau 	}
55263fd71a0aSMat Martineau 
55273fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
55283fd71a0aSMat Martineau 
55298d5a04a1SMat Martineau 	return 0;
55308d5a04a1SMat Martineau }
55318d5a04a1SMat Martineau 
5532de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
55332d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5534203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5535de73115aSClaudio Takahasi {
5536de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5537de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5538de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5539203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
55402ce603ebSClaudio Takahasi 	int err;
5541de73115aSClaudio Takahasi 
554240bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
5543de73115aSClaudio Takahasi 		return -EINVAL;
5544de73115aSClaudio Takahasi 
5545de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5546de73115aSClaudio Takahasi 		return -EPROTO;
5547de73115aSClaudio Takahasi 
5548de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5549de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5550de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5551de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5552de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5553de73115aSClaudio Takahasi 
5554de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5555de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5556de73115aSClaudio Takahasi 
5557de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
55582ce603ebSClaudio Takahasi 
5559d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
55602ce603ebSClaudio Takahasi 	if (err)
5561dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5562de73115aSClaudio Takahasi 	else
5563dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5564de73115aSClaudio Takahasi 
5565de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5566de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5567de73115aSClaudio Takahasi 
5568ffb5a827SAndre Guedes 	if (!err) {
5569f4869e2aSJohan Hedberg 		u8 store_hint;
5570ffb5a827SAndre Guedes 
5571f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
5572f4869e2aSJohan Hedberg 						to_multiplier);
5573f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
5574f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
5575f4869e2aSJohan Hedberg 				    to_multiplier);
5576f4869e2aSJohan Hedberg 
5577ffb5a827SAndre Guedes 	}
55782ce603ebSClaudio Takahasi 
5579de73115aSClaudio Takahasi 	return 0;
5580de73115aSClaudio Takahasi }
5581de73115aSClaudio Takahasi 
5582f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5583f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5584f1496deeSJohan Hedberg 				u8 *data)
5585f1496deeSJohan Hedberg {
5586f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
55873e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
5588f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5589f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
55903e64b7bdSJohan Hedberg 	int err, sec_level;
5591f1496deeSJohan Hedberg 
5592f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5593f1496deeSJohan Hedberg 		return -EPROTO;
5594f1496deeSJohan Hedberg 
5595f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5596f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5597f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5598f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5599f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5600f1496deeSJohan Hedberg 
5601571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
560240624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
560340624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
5604f1496deeSJohan Hedberg 		return -EPROTO;
5605f1496deeSJohan Hedberg 
5606f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5607f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5608f1496deeSJohan Hedberg 
5609f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5610f1496deeSJohan Hedberg 
5611f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5612f1496deeSJohan Hedberg 	if (!chan) {
5613f1496deeSJohan Hedberg 		err = -EBADSLT;
5614f1496deeSJohan Hedberg 		goto unlock;
5615f1496deeSJohan Hedberg 	}
5616f1496deeSJohan Hedberg 
5617f1496deeSJohan Hedberg 	err = 0;
5618f1496deeSJohan Hedberg 
5619f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5620f1496deeSJohan Hedberg 
5621f1496deeSJohan Hedberg 	switch (result) {
5622571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
562340624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
562440624183SJohan Hedberg 			err = -EBADSLT;
562540624183SJohan Hedberg 			break;
562640624183SJohan Hedberg 		}
562740624183SJohan Hedberg 
5628f1496deeSJohan Hedberg 		chan->ident = 0;
5629f1496deeSJohan Hedberg 		chan->dcid = dcid;
5630f1496deeSJohan Hedberg 		chan->omtu = mtu;
5631f1496deeSJohan Hedberg 		chan->remote_mps = mps;
56320cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5633f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5634f1496deeSJohan Hedberg 		break;
5635f1496deeSJohan Hedberg 
5636571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
5637571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
56383e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
56393e64b7bdSJohan Hedberg 		 * anything.
56403e64b7bdSJohan Hedberg 		 */
56413e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
56423e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
56433e64b7bdSJohan Hedberg 			break;
56443e64b7bdSJohan Hedberg 		}
56453e64b7bdSJohan Hedberg 
56463e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
56473e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
56483e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
56493e64b7bdSJohan Hedberg 
56503e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
56513e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
56523e64b7bdSJohan Hedberg 
56533e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
56543e64b7bdSJohan Hedberg 		break;
56553e64b7bdSJohan Hedberg 
5656f1496deeSJohan Hedberg 	default:
5657f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5658f1496deeSJohan Hedberg 		break;
5659f1496deeSJohan Hedberg 	}
5660f1496deeSJohan Hedberg 
5661f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5662f1496deeSJohan Hedberg 
5663f1496deeSJohan Hedberg unlock:
5664f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5665f1496deeSJohan Hedberg 
5666f1496deeSJohan Hedberg 	return err;
5667f1496deeSJohan Hedberg }
5668f1496deeSJohan Hedberg 
56693300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
56702d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
56712d792818SGustavo Padovan 				      u8 *data)
56723300d9a9SClaudio Takahasi {
56733300d9a9SClaudio Takahasi 	int err = 0;
56743300d9a9SClaudio Takahasi 
56753300d9a9SClaudio Takahasi 	switch (cmd->code) {
56763300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5677cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
56783300d9a9SClaudio Takahasi 		break;
56793300d9a9SClaudio Takahasi 
56803300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5681cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
56823300d9a9SClaudio Takahasi 		break;
56833300d9a9SClaudio Takahasi 
56843300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5685f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
56869245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
56873300d9a9SClaudio Takahasi 		break;
56883300d9a9SClaudio Takahasi 
56893300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
56903300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
56913300d9a9SClaudio Takahasi 		break;
56923300d9a9SClaudio Takahasi 
56933300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
56949245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
56953300d9a9SClaudio Takahasi 		break;
56963300d9a9SClaudio Takahasi 
56973300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5698cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
56993300d9a9SClaudio Takahasi 		break;
57003300d9a9SClaudio Takahasi 
57013300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
57029245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
57033300d9a9SClaudio Takahasi 		break;
57043300d9a9SClaudio Takahasi 
57053300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
57063300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
57073300d9a9SClaudio Takahasi 		break;
57083300d9a9SClaudio Takahasi 
57093300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
57103300d9a9SClaudio Takahasi 		break;
57113300d9a9SClaudio Takahasi 
57123300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5713cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
57143300d9a9SClaudio Takahasi 		break;
57153300d9a9SClaudio Takahasi 
57163300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
57179245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
57183300d9a9SClaudio Takahasi 		break;
57193300d9a9SClaudio Takahasi 
5720f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5721f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5722f94ff6ffSMat Martineau 		break;
5723f94ff6ffSMat Martineau 
57248d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
57258d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
57268d5a04a1SMat Martineau 		break;
57278d5a04a1SMat Martineau 
57288d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
57299245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
57308d5a04a1SMat Martineau 		break;
57318d5a04a1SMat Martineau 
57328d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
57338d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
57348d5a04a1SMat Martineau 		break;
57358d5a04a1SMat Martineau 
57368d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
57379245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
57388d5a04a1SMat Martineau 		break;
57398d5a04a1SMat Martineau 
57403300d9a9SClaudio Takahasi 	default:
57413300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
57423300d9a9SClaudio Takahasi 		err = -EINVAL;
57433300d9a9SClaudio Takahasi 		break;
57443300d9a9SClaudio Takahasi 	}
57453300d9a9SClaudio Takahasi 
57463300d9a9SClaudio Takahasi 	return err;
57473300d9a9SClaudio Takahasi }
57483300d9a9SClaudio Takahasi 
574927e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
575027e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
575127e2d4c8SJohan Hedberg 				u8 *data)
575227e2d4c8SJohan Hedberg {
575327e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
575427e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
575527e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
57560cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
575727e2d4c8SJohan Hedberg 	__le16 psm;
575827e2d4c8SJohan Hedberg 	u8 result;
575927e2d4c8SJohan Hedberg 
576027e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
576127e2d4c8SJohan Hedberg 		return -EPROTO;
576227e2d4c8SJohan Hedberg 
576327e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
576427e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
576527e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
576627e2d4c8SJohan Hedberg 	psm  = req->psm;
576727e2d4c8SJohan Hedberg 	dcid = 0;
57680cd75f7eSJohan Hedberg 	credits = 0;
576927e2d4c8SJohan Hedberg 
577027e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
577127e2d4c8SJohan Hedberg 		return -EPROTO;
577227e2d4c8SJohan Hedberg 
577327e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
577427e2d4c8SJohan Hedberg 	       scid, mtu, mps);
577527e2d4c8SJohan Hedberg 
577627e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
577727e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
577827e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
577927e2d4c8SJohan Hedberg 	if (!pchan) {
5780571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
578127e2d4c8SJohan Hedberg 		chan = NULL;
578227e2d4c8SJohan Hedberg 		goto response;
578327e2d4c8SJohan Hedberg 	}
578427e2d4c8SJohan Hedberg 
578527e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
578627e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
578727e2d4c8SJohan Hedberg 
578835dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
578935dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
5790571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
579127e2d4c8SJohan Hedberg 		chan = NULL;
579227e2d4c8SJohan Hedberg 		goto response_unlock;
579327e2d4c8SJohan Hedberg 	}
579427e2d4c8SJohan Hedberg 
57958a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
57968a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
5797571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
57988a7889ccSJohan Hedberg 		chan = NULL;
57998a7889ccSJohan Hedberg 		goto response_unlock;
58008a7889ccSJohan Hedberg 	}
58018a7889ccSJohan Hedberg 
580227e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
580327e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
5804571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
580527e2d4c8SJohan Hedberg 		chan = NULL;
580627e2d4c8SJohan Hedberg 		goto response_unlock;
580727e2d4c8SJohan Hedberg 	}
580827e2d4c8SJohan Hedberg 
580927e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
581027e2d4c8SJohan Hedberg 	if (!chan) {
5811571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
581227e2d4c8SJohan Hedberg 		goto response_unlock;
581327e2d4c8SJohan Hedberg 	}
581427e2d4c8SJohan Hedberg 
581527e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
581627e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
5817a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
5818a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
581927e2d4c8SJohan Hedberg 	chan->psm  = psm;
582027e2d4c8SJohan Hedberg 	chan->dcid = scid;
582127e2d4c8SJohan Hedberg 	chan->omtu = mtu;
582227e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
582327e2d4c8SJohan Hedberg 
582427e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
5825fe149310SLuiz Augusto von Dentz 
5826ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
5827fe149310SLuiz Augusto von Dentz 
582827e2d4c8SJohan Hedberg 	dcid = chan->scid;
58290cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
583027e2d4c8SJohan Hedberg 
583127e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
583227e2d4c8SJohan Hedberg 
583327e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
583427e2d4c8SJohan Hedberg 
583527e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
583627e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
5837434714dcSJohan Hedberg 		/* The following result value is actually not defined
5838434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
5839434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
5840434714dcSJohan Hedberg 		 * instead of sending a response.
5841434714dcSJohan Hedberg 		 */
584227e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
584327e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
584427e2d4c8SJohan Hedberg 	} else {
584527e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
5846571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
584727e2d4c8SJohan Hedberg 	}
584827e2d4c8SJohan Hedberg 
584927e2d4c8SJohan Hedberg response_unlock:
585027e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
585127e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5852a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
585327e2d4c8SJohan Hedberg 
585427e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
585527e2d4c8SJohan Hedberg 		return 0;
585627e2d4c8SJohan Hedberg 
585727e2d4c8SJohan Hedberg response:
585827e2d4c8SJohan Hedberg 	if (chan) {
585927e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
58603916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
586127e2d4c8SJohan Hedberg 	} else {
586227e2d4c8SJohan Hedberg 		rsp.mtu = 0;
586327e2d4c8SJohan Hedberg 		rsp.mps = 0;
586427e2d4c8SJohan Hedberg 	}
586527e2d4c8SJohan Hedberg 
586627e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
58670cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
586827e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
586927e2d4c8SJohan Hedberg 
587027e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
587127e2d4c8SJohan Hedberg 
587227e2d4c8SJohan Hedberg 	return 0;
587327e2d4c8SJohan Hedberg }
587427e2d4c8SJohan Hedberg 
5875fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5876fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5877fad5fc89SJohan Hedberg 				   u8 *data)
5878fad5fc89SJohan Hedberg {
5879fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5880fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
58810f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
5882fad5fc89SJohan Hedberg 
5883fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5884fad5fc89SJohan Hedberg 		return -EPROTO;
5885fad5fc89SJohan Hedberg 
5886fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5887fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5888fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5889fad5fc89SJohan Hedberg 
5890fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5891fad5fc89SJohan Hedberg 
5892fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5893fad5fc89SJohan Hedberg 	if (!chan)
5894fad5fc89SJohan Hedberg 		return -EBADSLT;
5895fad5fc89SJohan Hedberg 
58960f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
58970f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
58980f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
58990f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
5900ee93053dSMartin Townsend 		l2cap_chan_unlock(chan);
59010f1bfe4eSJohan Hedberg 
59020f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
59030f1bfe4eSJohan Hedberg 		 * command reject packet.
59040f1bfe4eSJohan Hedberg 		 */
59050f1bfe4eSJohan Hedberg 		return 0;
59060f1bfe4eSJohan Hedberg 	}
59070f1bfe4eSJohan Hedberg 
5908fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5909fad5fc89SJohan Hedberg 
59108a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
59118a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
5912fad5fc89SJohan Hedberg 
5913fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5914fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5915fad5fc89SJohan Hedberg 
5916fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5917fad5fc89SJohan Hedberg 
5918fad5fc89SJohan Hedberg 	return 0;
5919fad5fc89SJohan Hedberg }
5920fad5fc89SJohan Hedberg 
592115f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
592215f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
592315f02b91SLuiz Augusto von Dentz 				       u8 *data)
592415f02b91SLuiz Augusto von Dentz {
592515f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_req *req = (void *) data;
592615f02b91SLuiz Augusto von Dentz 	struct {
592715f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
59287cf3b1ddSLuiz Augusto von Dentz 		__le16 dcid[L2CAP_ECRED_MAX_CID];
592915f02b91SLuiz Augusto von Dentz 	} __packed pdu;
593015f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *pchan;
5931965995b7SYueHaibing 	u16 mtu, mps;
593215f02b91SLuiz Augusto von Dentz 	__le16 psm;
593315f02b91SLuiz Augusto von Dentz 	u8 result, len = 0;
593415f02b91SLuiz Augusto von Dentz 	int i, num_scid;
593515f02b91SLuiz Augusto von Dentz 	bool defer = false;
593615f02b91SLuiz Augusto von Dentz 
59374be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
59384be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
59394be5ca67SLuiz Augusto von Dentz 
594069d67b46SKonstantin Forostyan 	if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
594115f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
594215f02b91SLuiz Augusto von Dentz 		goto response;
594315f02b91SLuiz Augusto von Dentz 	}
594415f02b91SLuiz Augusto von Dentz 
59457cf3b1ddSLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
59467cf3b1ddSLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
59477cf3b1ddSLuiz Augusto von Dentz 
59487cf3b1ddSLuiz Augusto von Dentz 	if (num_scid > ARRAY_SIZE(pdu.dcid)) {
59497cf3b1ddSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
59507cf3b1ddSLuiz Augusto von Dentz 		goto response;
59517cf3b1ddSLuiz Augusto von Dentz 	}
59527cf3b1ddSLuiz Augusto von Dentz 
595315f02b91SLuiz Augusto von Dentz 	mtu  = __le16_to_cpu(req->mtu);
595415f02b91SLuiz Augusto von Dentz 	mps  = __le16_to_cpu(req->mps);
595515f02b91SLuiz Augusto von Dentz 
595615f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
595715f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_UNACCEPT_PARAMS;
595815f02b91SLuiz Augusto von Dentz 		goto response;
595915f02b91SLuiz Augusto von Dentz 	}
596015f02b91SLuiz Augusto von Dentz 
596115f02b91SLuiz Augusto von Dentz 	psm  = req->psm;
596215f02b91SLuiz Augusto von Dentz 
596315f02b91SLuiz Augusto von Dentz 	BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
596415f02b91SLuiz Augusto von Dentz 
596515f02b91SLuiz Augusto von Dentz 	memset(&pdu, 0, sizeof(pdu));
596615f02b91SLuiz Augusto von Dentz 
596715f02b91SLuiz Augusto von Dentz 	/* Check if we have socket listening on psm */
596815f02b91SLuiz Augusto von Dentz 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
596915f02b91SLuiz Augusto von Dentz 					 &conn->hcon->dst, LE_LINK);
597015f02b91SLuiz Augusto von Dentz 	if (!pchan) {
597115f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
597215f02b91SLuiz Augusto von Dentz 		goto response;
597315f02b91SLuiz Augusto von Dentz 	}
597415f02b91SLuiz Augusto von Dentz 
597515f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
597615f02b91SLuiz Augusto von Dentz 	l2cap_chan_lock(pchan);
597715f02b91SLuiz Augusto von Dentz 
597815f02b91SLuiz Augusto von Dentz 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
597915f02b91SLuiz Augusto von Dentz 				     SMP_ALLOW_STK)) {
598015f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHENTICATION;
598115f02b91SLuiz Augusto von Dentz 		goto unlock;
598215f02b91SLuiz Augusto von Dentz 	}
598315f02b91SLuiz Augusto von Dentz 
598415f02b91SLuiz Augusto von Dentz 	result = L2CAP_CR_LE_SUCCESS;
598515f02b91SLuiz Augusto von Dentz 
598615f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
598715f02b91SLuiz Augusto von Dentz 		u16 scid = __le16_to_cpu(req->scid[i]);
598815f02b91SLuiz Augusto von Dentz 
598915f02b91SLuiz Augusto von Dentz 		BT_DBG("scid[%d] 0x%4.4x", i, scid);
599015f02b91SLuiz Augusto von Dentz 
599115f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = 0x0000;
599215f02b91SLuiz Augusto von Dentz 		len += sizeof(*pdu.dcid);
599315f02b91SLuiz Augusto von Dentz 
599415f02b91SLuiz Augusto von Dentz 		/* Check for valid dynamic CID range */
599515f02b91SLuiz Augusto von Dentz 		if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
599615f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_INVALID_SCID;
599715f02b91SLuiz Augusto von Dentz 			continue;
599815f02b91SLuiz Augusto von Dentz 		}
599915f02b91SLuiz Augusto von Dentz 
600015f02b91SLuiz Augusto von Dentz 		/* Check if we already have channel with that dcid */
600115f02b91SLuiz Augusto von Dentz 		if (__l2cap_get_chan_by_dcid(conn, scid)) {
600215f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_SCID_IN_USE;
600315f02b91SLuiz Augusto von Dentz 			continue;
600415f02b91SLuiz Augusto von Dentz 		}
600515f02b91SLuiz Augusto von Dentz 
600615f02b91SLuiz Augusto von Dentz 		chan = pchan->ops->new_connection(pchan);
600715f02b91SLuiz Augusto von Dentz 		if (!chan) {
600815f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_NO_MEM;
600915f02b91SLuiz Augusto von Dentz 			continue;
601015f02b91SLuiz Augusto von Dentz 		}
601115f02b91SLuiz Augusto von Dentz 
601215f02b91SLuiz Augusto von Dentz 		bacpy(&chan->src, &conn->hcon->src);
601315f02b91SLuiz Augusto von Dentz 		bacpy(&chan->dst, &conn->hcon->dst);
601415f02b91SLuiz Augusto von Dentz 		chan->src_type = bdaddr_src_type(conn->hcon);
601515f02b91SLuiz Augusto von Dentz 		chan->dst_type = bdaddr_dst_type(conn->hcon);
601615f02b91SLuiz Augusto von Dentz 		chan->psm  = psm;
601715f02b91SLuiz Augusto von Dentz 		chan->dcid = scid;
601815f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
601915f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
602015f02b91SLuiz Augusto von Dentz 
602115f02b91SLuiz Augusto von Dentz 		__l2cap_chan_add(conn, chan);
602215f02b91SLuiz Augusto von Dentz 
602315f02b91SLuiz Augusto von Dentz 		l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
602415f02b91SLuiz Augusto von Dentz 
602515f02b91SLuiz Augusto von Dentz 		/* Init response */
602615f02b91SLuiz Augusto von Dentz 		if (!pdu.rsp.credits) {
602715f02b91SLuiz Augusto von Dentz 			pdu.rsp.mtu = cpu_to_le16(chan->imtu);
602815f02b91SLuiz Augusto von Dentz 			pdu.rsp.mps = cpu_to_le16(chan->mps);
602915f02b91SLuiz Augusto von Dentz 			pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
603015f02b91SLuiz Augusto von Dentz 		}
603115f02b91SLuiz Augusto von Dentz 
603215f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = cpu_to_le16(chan->scid);
603315f02b91SLuiz Augusto von Dentz 
603415f02b91SLuiz Augusto von Dentz 		__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
603515f02b91SLuiz Augusto von Dentz 
603615f02b91SLuiz Augusto von Dentz 		chan->ident = cmd->ident;
603715f02b91SLuiz Augusto von Dentz 
603815f02b91SLuiz Augusto von Dentz 		if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
603915f02b91SLuiz Augusto von Dentz 			l2cap_state_change(chan, BT_CONNECT2);
604015f02b91SLuiz Augusto von Dentz 			defer = true;
604115f02b91SLuiz Augusto von Dentz 			chan->ops->defer(chan);
604215f02b91SLuiz Augusto von Dentz 		} else {
604315f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
604415f02b91SLuiz Augusto von Dentz 		}
604515f02b91SLuiz Augusto von Dentz 	}
604615f02b91SLuiz Augusto von Dentz 
604715f02b91SLuiz Augusto von Dentz unlock:
604815f02b91SLuiz Augusto von Dentz 	l2cap_chan_unlock(pchan);
604915f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
605015f02b91SLuiz Augusto von Dentz 	l2cap_chan_put(pchan);
605115f02b91SLuiz Augusto von Dentz 
605215f02b91SLuiz Augusto von Dentz response:
605315f02b91SLuiz Augusto von Dentz 	pdu.rsp.result = cpu_to_le16(result);
605415f02b91SLuiz Augusto von Dentz 
605515f02b91SLuiz Augusto von Dentz 	if (defer)
605615f02b91SLuiz Augusto von Dentz 		return 0;
605715f02b91SLuiz Augusto von Dentz 
605815f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
605915f02b91SLuiz Augusto von Dentz 		       sizeof(pdu.rsp) + len, &pdu);
606015f02b91SLuiz Augusto von Dentz 
606115f02b91SLuiz Augusto von Dentz 	return 0;
606215f02b91SLuiz Augusto von Dentz }
606315f02b91SLuiz Augusto von Dentz 
606415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
606515f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
606615f02b91SLuiz Augusto von Dentz 				       u8 *data)
606715f02b91SLuiz Augusto von Dentz {
606815f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
606915f02b91SLuiz Augusto von Dentz 	struct hci_conn *hcon = conn->hcon;
607015f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, credits, result;
607115f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
607215f02b91SLuiz Augusto von Dentz 	int err = 0, sec_level;
607315f02b91SLuiz Augusto von Dentz 	int i = 0;
607415f02b91SLuiz Augusto von Dentz 
607515f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
607615f02b91SLuiz Augusto von Dentz 		return -EPROTO;
607715f02b91SLuiz Augusto von Dentz 
607815f02b91SLuiz Augusto von Dentz 	mtu     = __le16_to_cpu(rsp->mtu);
607915f02b91SLuiz Augusto von Dentz 	mps     = __le16_to_cpu(rsp->mps);
608015f02b91SLuiz Augusto von Dentz 	credits = __le16_to_cpu(rsp->credits);
608115f02b91SLuiz Augusto von Dentz 	result  = __le16_to_cpu(rsp->result);
608215f02b91SLuiz Augusto von Dentz 
608315f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
608415f02b91SLuiz Augusto von Dentz 	       result);
608515f02b91SLuiz Augusto von Dentz 
608615f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
608715f02b91SLuiz Augusto von Dentz 
608815f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*rsp);
608915f02b91SLuiz Augusto von Dentz 
609015f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
609115f02b91SLuiz Augusto von Dentz 		u16 dcid;
609215f02b91SLuiz Augusto von Dentz 
609315f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident ||
609415f02b91SLuiz Augusto von Dentz 		    chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
609515f02b91SLuiz Augusto von Dentz 		    chan->state == BT_CONNECTED)
609615f02b91SLuiz Augusto von Dentz 			continue;
609715f02b91SLuiz Augusto von Dentz 
609815f02b91SLuiz Augusto von Dentz 		l2cap_chan_lock(chan);
609915f02b91SLuiz Augusto von Dentz 
610015f02b91SLuiz Augusto von Dentz 		/* Check that there is a dcid for each pending channel */
610115f02b91SLuiz Augusto von Dentz 		if (cmd_len < sizeof(dcid)) {
610215f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
610315f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
610415f02b91SLuiz Augusto von Dentz 			continue;
610515f02b91SLuiz Augusto von Dentz 		}
610615f02b91SLuiz Augusto von Dentz 
610715f02b91SLuiz Augusto von Dentz 		dcid = __le16_to_cpu(rsp->dcid[i++]);
610815f02b91SLuiz Augusto von Dentz 		cmd_len -= sizeof(u16);
610915f02b91SLuiz Augusto von Dentz 
611015f02b91SLuiz Augusto von Dentz 		BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
611115f02b91SLuiz Augusto von Dentz 
611215f02b91SLuiz Augusto von Dentz 		/* Check if dcid is already in use */
611315f02b91SLuiz Augusto von Dentz 		if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
611415f02b91SLuiz Augusto von Dentz 			/* If a device receives a
611515f02b91SLuiz Augusto von Dentz 			 * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
611615f02b91SLuiz Augusto von Dentz 			 * already-assigned Destination CID, then both the
611715f02b91SLuiz Augusto von Dentz 			 * original channel and the new channel shall be
611815f02b91SLuiz Augusto von Dentz 			 * immediately discarded and not used.
611915f02b91SLuiz Augusto von Dentz 			 */
612015f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
612115f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
612215f02b91SLuiz Augusto von Dentz 			chan = __l2cap_get_chan_by_dcid(conn, dcid);
612315f02b91SLuiz Augusto von Dentz 			l2cap_chan_lock(chan);
612415f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNRESET);
612515f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
612615f02b91SLuiz Augusto von Dentz 			continue;
612715f02b91SLuiz Augusto von Dentz 		}
612815f02b91SLuiz Augusto von Dentz 
612915f02b91SLuiz Augusto von Dentz 		switch (result) {
613015f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_AUTHENTICATION:
613115f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_ENCRYPTION:
613215f02b91SLuiz Augusto von Dentz 			/* If we already have MITM protection we can't do
613315f02b91SLuiz Augusto von Dentz 			 * anything.
613415f02b91SLuiz Augusto von Dentz 			 */
613515f02b91SLuiz Augusto von Dentz 			if (hcon->sec_level > BT_SECURITY_MEDIUM) {
613615f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
613715f02b91SLuiz Augusto von Dentz 				break;
613815f02b91SLuiz Augusto von Dentz 			}
613915f02b91SLuiz Augusto von Dentz 
614015f02b91SLuiz Augusto von Dentz 			sec_level = hcon->sec_level + 1;
614115f02b91SLuiz Augusto von Dentz 			if (chan->sec_level < sec_level)
614215f02b91SLuiz Augusto von Dentz 				chan->sec_level = sec_level;
614315f02b91SLuiz Augusto von Dentz 
614415f02b91SLuiz Augusto von Dentz 			/* We'll need to send a new Connect Request */
614515f02b91SLuiz Augusto von Dentz 			clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
614615f02b91SLuiz Augusto von Dentz 
614715f02b91SLuiz Augusto von Dentz 			smp_conn_security(hcon, chan->sec_level);
614815f02b91SLuiz Augusto von Dentz 			break;
614915f02b91SLuiz Augusto von Dentz 
615015f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_BAD_PSM:
615115f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
615215f02b91SLuiz Augusto von Dentz 			break;
615315f02b91SLuiz Augusto von Dentz 
615415f02b91SLuiz Augusto von Dentz 		default:
615515f02b91SLuiz Augusto von Dentz 			/* If dcid was not set it means channels was refused */
615615f02b91SLuiz Augusto von Dentz 			if (!dcid) {
615715f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
615815f02b91SLuiz Augusto von Dentz 				break;
615915f02b91SLuiz Augusto von Dentz 			}
616015f02b91SLuiz Augusto von Dentz 
616115f02b91SLuiz Augusto von Dentz 			chan->ident = 0;
616215f02b91SLuiz Augusto von Dentz 			chan->dcid = dcid;
616315f02b91SLuiz Augusto von Dentz 			chan->omtu = mtu;
616415f02b91SLuiz Augusto von Dentz 			chan->remote_mps = mps;
616515f02b91SLuiz Augusto von Dentz 			chan->tx_credits = credits;
616615f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
616715f02b91SLuiz Augusto von Dentz 			break;
616815f02b91SLuiz Augusto von Dentz 		}
616915f02b91SLuiz Augusto von Dentz 
617015f02b91SLuiz Augusto von Dentz 		l2cap_chan_unlock(chan);
617115f02b91SLuiz Augusto von Dentz 	}
617215f02b91SLuiz Augusto von Dentz 
617315f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
617415f02b91SLuiz Augusto von Dentz 
617515f02b91SLuiz Augusto von Dentz 	return err;
617615f02b91SLuiz Augusto von Dentz }
617715f02b91SLuiz Augusto von Dentz 
617815f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
617915f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
618015f02b91SLuiz Augusto von Dentz 					 u8 *data)
618115f02b91SLuiz Augusto von Dentz {
618215f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_req *req = (void *) data;
618315f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_rsp rsp;
618415f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, result;
618515f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
618615f02b91SLuiz Augusto von Dentz 	int i, num_scid;
618715f02b91SLuiz Augusto von Dentz 
61884be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
61894be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
61904be5ca67SLuiz Augusto von Dentz 
619115f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
619215f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
619315f02b91SLuiz Augusto von Dentz 		goto respond;
619415f02b91SLuiz Augusto von Dentz 	}
619515f02b91SLuiz Augusto von Dentz 
619615f02b91SLuiz Augusto von Dentz 	mtu = __le16_to_cpu(req->mtu);
619715f02b91SLuiz Augusto von Dentz 	mps = __le16_to_cpu(req->mps);
619815f02b91SLuiz Augusto von Dentz 
619915f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u", mtu, mps);
620015f02b91SLuiz Augusto von Dentz 
620115f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU) {
620215f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MTU;
620315f02b91SLuiz Augusto von Dentz 		goto respond;
620415f02b91SLuiz Augusto von Dentz 	}
620515f02b91SLuiz Augusto von Dentz 
620615f02b91SLuiz Augusto von Dentz 	if (mps < L2CAP_ECRED_MIN_MPS) {
620715f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MPS;
620815f02b91SLuiz Augusto von Dentz 		goto respond;
620915f02b91SLuiz Augusto von Dentz 	}
621015f02b91SLuiz Augusto von Dentz 
621115f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
621215f02b91SLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
621315f02b91SLuiz Augusto von Dentz 	result = L2CAP_RECONF_SUCCESS;
621415f02b91SLuiz Augusto von Dentz 
621515f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
621615f02b91SLuiz Augusto von Dentz 		u16 scid;
621715f02b91SLuiz Augusto von Dentz 
621815f02b91SLuiz Augusto von Dentz 		scid = __le16_to_cpu(req->scid[i]);
621915f02b91SLuiz Augusto von Dentz 		if (!scid)
622015f02b91SLuiz Augusto von Dentz 			return -EPROTO;
622115f02b91SLuiz Augusto von Dentz 
622215f02b91SLuiz Augusto von Dentz 		chan = __l2cap_get_chan_by_dcid(conn, scid);
622315f02b91SLuiz Augusto von Dentz 		if (!chan)
622415f02b91SLuiz Augusto von Dentz 			continue;
622515f02b91SLuiz Augusto von Dentz 
622615f02b91SLuiz Augusto von Dentz 		/* If the MTU value is decreased for any of the included
622715f02b91SLuiz Augusto von Dentz 		 * channels, then the receiver shall disconnect all
622815f02b91SLuiz Augusto von Dentz 		 * included channels.
622915f02b91SLuiz Augusto von Dentz 		 */
623015f02b91SLuiz Augusto von Dentz 		if (chan->omtu > mtu) {
623115f02b91SLuiz Augusto von Dentz 			BT_ERR("chan %p decreased MTU %u -> %u", chan,
623215f02b91SLuiz Augusto von Dentz 			       chan->omtu, mtu);
623315f02b91SLuiz Augusto von Dentz 			result = L2CAP_RECONF_INVALID_MTU;
623415f02b91SLuiz Augusto von Dentz 		}
623515f02b91SLuiz Augusto von Dentz 
623615f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
623715f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
623815f02b91SLuiz Augusto von Dentz 	}
623915f02b91SLuiz Augusto von Dentz 
624015f02b91SLuiz Augusto von Dentz respond:
624115f02b91SLuiz Augusto von Dentz 	rsp.result = cpu_to_le16(result);
624215f02b91SLuiz Augusto von Dentz 
624315f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
624415f02b91SLuiz Augusto von Dentz 		       &rsp);
624515f02b91SLuiz Augusto von Dentz 
624615f02b91SLuiz Augusto von Dentz 	return 0;
624715f02b91SLuiz Augusto von Dentz }
624815f02b91SLuiz Augusto von Dentz 
624915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
625015f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
625115f02b91SLuiz Augusto von Dentz 					 u8 *data)
625215f02b91SLuiz Augusto von Dentz {
625315f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
625415f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
625515f02b91SLuiz Augusto von Dentz 	u16 result;
625615f02b91SLuiz Augusto von Dentz 
625715f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
625815f02b91SLuiz Augusto von Dentz 		return -EPROTO;
625915f02b91SLuiz Augusto von Dentz 
626015f02b91SLuiz Augusto von Dentz 	result = __le16_to_cpu(rsp->result);
626115f02b91SLuiz Augusto von Dentz 
626215f02b91SLuiz Augusto von Dentz 	BT_DBG("result 0x%4.4x", rsp->result);
626315f02b91SLuiz Augusto von Dentz 
626415f02b91SLuiz Augusto von Dentz 	if (!result)
626515f02b91SLuiz Augusto von Dentz 		return 0;
626615f02b91SLuiz Augusto von Dentz 
626715f02b91SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
626815f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident)
626915f02b91SLuiz Augusto von Dentz 			continue;
627015f02b91SLuiz Augusto von Dentz 
627115f02b91SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
627215f02b91SLuiz Augusto von Dentz 	}
627315f02b91SLuiz Augusto von Dentz 
627415f02b91SLuiz Augusto von Dentz 	return 0;
627515f02b91SLuiz Augusto von Dentz }
627615f02b91SLuiz Augusto von Dentz 
627771fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
627871fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
627971fb4197SJohan Hedberg 				       u8 *data)
628071fb4197SJohan Hedberg {
628171fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
628271fb4197SJohan Hedberg 	struct l2cap_chan *chan;
628371fb4197SJohan Hedberg 
628471fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
628571fb4197SJohan Hedberg 		return -EPROTO;
628671fb4197SJohan Hedberg 
628771fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
628871fb4197SJohan Hedberg 
628971fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
629071fb4197SJohan Hedberg 	if (!chan)
629171fb4197SJohan Hedberg 		goto done;
629271fb4197SJohan Hedberg 
629371fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
629471fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
629571fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
629671fb4197SJohan Hedberg 
629771fb4197SJohan Hedberg done:
629871fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
629971fb4197SJohan Hedberg 	return 0;
630071fb4197SJohan Hedberg }
630171fb4197SJohan Hedberg 
63023300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
6303203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
6304203e639eSJohan Hedberg 				   u8 *data)
63053300d9a9SClaudio Takahasi {
6306b5ecba64SJohan Hedberg 	int err = 0;
6307b5ecba64SJohan Hedberg 
63083300d9a9SClaudio Takahasi 	switch (cmd->code) {
63093300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
631071fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
6311b5ecba64SJohan Hedberg 		break;
63123300d9a9SClaudio Takahasi 
63133300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
6314b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
6315b5ecba64SJohan Hedberg 		break;
63163300d9a9SClaudio Takahasi 
63173300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
6318b5ecba64SJohan Hedberg 		break;
63193300d9a9SClaudio Takahasi 
6320f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
6321f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
6322b5ecba64SJohan Hedberg 		break;
6323f1496deeSJohan Hedberg 
632427e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
6325b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
6326b5ecba64SJohan Hedberg 		break;
632727e2d4c8SJohan Hedberg 
6328fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
6329fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
6330fad5fc89SJohan Hedberg 		break;
6331fad5fc89SJohan Hedberg 
633215f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_REQ:
633315f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
633415f02b91SLuiz Augusto von Dentz 		break;
633515f02b91SLuiz Augusto von Dentz 
633615f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_RSP:
633715f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
633815f02b91SLuiz Augusto von Dentz 		break;
633915f02b91SLuiz Augusto von Dentz 
634015f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_REQ:
634115f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
634215f02b91SLuiz Augusto von Dentz 		break;
634315f02b91SLuiz Augusto von Dentz 
634415f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_RSP:
634515f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
634615f02b91SLuiz Augusto von Dentz 		break;
634715f02b91SLuiz Augusto von Dentz 
63483defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
6349b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
6350b5ecba64SJohan Hedberg 		break;
63513defe01aSJohan Hedberg 
63523defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
63533defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
6354b5ecba64SJohan Hedberg 		break;
63553defe01aSJohan Hedberg 
63563300d9a9SClaudio Takahasi 	default:
63573300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
6358b5ecba64SJohan Hedberg 		err = -EINVAL;
6359b5ecba64SJohan Hedberg 		break;
63603300d9a9SClaudio Takahasi 	}
6361b5ecba64SJohan Hedberg 
6362b5ecba64SJohan Hedberg 	return err;
63633300d9a9SClaudio Takahasi }
63643300d9a9SClaudio Takahasi 
6365c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
6366c5623556SJohan Hedberg 					struct sk_buff *skb)
6367c5623556SJohan Hedberg {
636869c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
63694f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
63704f3e219dSMarcel Holtmann 	u16 len;
6371c5623556SJohan Hedberg 	int err;
6372c5623556SJohan Hedberg 
637369c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
63743b166295SMarcel Holtmann 		goto drop;
637569c4e4e8SJohan Hedberg 
63764f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
63774f3e219dSMarcel Holtmann 		goto drop;
6378c5623556SJohan Hedberg 
63794f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
63804f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
6381c5623556SJohan Hedberg 
63824f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
6383c5623556SJohan Hedberg 
63844f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
63854f3e219dSMarcel Holtmann 
63864f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
6387c5623556SJohan Hedberg 		BT_DBG("corrupted command");
63884f3e219dSMarcel Holtmann 		goto drop;
6389c5623556SJohan Hedberg 	}
6390c5623556SJohan Hedberg 
6391203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
6392c5623556SJohan Hedberg 	if (err) {
6393c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
6394c5623556SJohan Hedberg 
6395c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
6396c5623556SJohan Hedberg 
6397dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
63984f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
6399c5623556SJohan Hedberg 			       sizeof(rej), &rej);
6400c5623556SJohan Hedberg 	}
6401c5623556SJohan Hedberg 
64023b166295SMarcel Holtmann drop:
6403c5623556SJohan Hedberg 	kfree_skb(skb);
6404c5623556SJohan Hedberg }
6405c5623556SJohan Hedberg 
64063300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
64073300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
64080a708f8fSGustavo F. Padovan {
640969c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
641055cee73eSLuiz Augusto von Dentz 	struct l2cap_cmd_hdr *cmd;
64113300d9a9SClaudio Takahasi 	int err;
64120a708f8fSGustavo F. Padovan 
64130a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
64140a708f8fSGustavo F. Padovan 
641569c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
64163b166295SMarcel Holtmann 		goto drop;
641769c4e4e8SJohan Hedberg 
641855cee73eSLuiz Augusto von Dentz 	while (skb->len >= L2CAP_CMD_HDR_SIZE) {
641955cee73eSLuiz Augusto von Dentz 		u16 len;
64200a708f8fSGustavo F. Padovan 
642155cee73eSLuiz Augusto von Dentz 		cmd = (void *) skb->data;
642255cee73eSLuiz Augusto von Dentz 		skb_pull(skb, L2CAP_CMD_HDR_SIZE);
64230a708f8fSGustavo F. Padovan 
642455cee73eSLuiz Augusto von Dentz 		len = le16_to_cpu(cmd->len);
64250a708f8fSGustavo F. Padovan 
642655cee73eSLuiz Augusto von Dentz 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
642755cee73eSLuiz Augusto von Dentz 		       cmd->ident);
642855cee73eSLuiz Augusto von Dentz 
642955cee73eSLuiz Augusto von Dentz 		if (len > skb->len || !cmd->ident) {
64300a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
64310a708f8fSGustavo F. Padovan 			break;
64320a708f8fSGustavo F. Padovan 		}
64330a708f8fSGustavo F. Padovan 
643455cee73eSLuiz Augusto von Dentz 		err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
64350a708f8fSGustavo F. Padovan 		if (err) {
6436e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
64372c6d1a2eSGustavo F. Padovan 
64382c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
64390a708f8fSGustavo F. Padovan 
6440dcf4adbfSJoe Perches 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
644155cee73eSLuiz Augusto von Dentz 			l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
64422d792818SGustavo Padovan 				       sizeof(rej), &rej);
64430a708f8fSGustavo F. Padovan 		}
64440a708f8fSGustavo F. Padovan 
644555cee73eSLuiz Augusto von Dentz 		skb_pull(skb, len);
64460a708f8fSGustavo F. Padovan 	}
64470a708f8fSGustavo F. Padovan 
64483b166295SMarcel Holtmann drop:
64490a708f8fSGustavo F. Padovan 	kfree_skb(skb);
64500a708f8fSGustavo F. Padovan }
64510a708f8fSGustavo F. Padovan 
645247d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
64530a708f8fSGustavo F. Padovan {
64540a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
6455e4ca6d98SAndrei Emeltchenko 	int hdr_size;
6456e4ca6d98SAndrei Emeltchenko 
6457e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
6458e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
6459e4ca6d98SAndrei Emeltchenko 	else
6460e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
64610a708f8fSGustavo F. Padovan 
646247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
646303a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
64640a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
64650a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
64660a708f8fSGustavo F. Padovan 
64670a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
64680a708f8fSGustavo F. Padovan 			return -EBADMSG;
64690a708f8fSGustavo F. Padovan 	}
64700a708f8fSGustavo F. Padovan 	return 0;
64710a708f8fSGustavo F. Padovan }
64720a708f8fSGustavo F. Padovan 
64736ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
64740a708f8fSGustavo F. Padovan {
6475e31f7633SMat Martineau 	struct l2cap_ctrl control;
64760a708f8fSGustavo F. Padovan 
6477e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
64780a708f8fSGustavo F. Padovan 
6479e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
6480e31f7633SMat Martineau 	control.sframe = 1;
6481e31f7633SMat Martineau 	control.final = 1;
6482e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
6483e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
64840a708f8fSGustavo F. Padovan 
6485e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6486e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
6487e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
64880a708f8fSGustavo F. Padovan 	}
64890a708f8fSGustavo F. Padovan 
6490e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
6491e31f7633SMat Martineau 	    chan->unacked_frames > 0)
6492e31f7633SMat Martineau 		__set_retrans_timer(chan);
64930a708f8fSGustavo F. Padovan 
6494e31f7633SMat Martineau 	/* Send pending iframes */
6495525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
64960a708f8fSGustavo F. Padovan 
6497e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
6498e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
6499e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
6500e31f7633SMat Martineau 		 * send it now.
6501e31f7633SMat Martineau 		 */
6502e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
6503e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
65040a708f8fSGustavo F. Padovan 	}
65050a708f8fSGustavo F. Padovan }
65060a708f8fSGustavo F. Padovan 
65072d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
65082d792818SGustavo Padovan 			    struct sk_buff **last_frag)
65090a708f8fSGustavo F. Padovan {
651084084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
651184084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
651284084a31SMat Martineau 	 */
651384084a31SMat Martineau 	if (!skb_has_frag_list(skb))
651484084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
651584084a31SMat Martineau 
651684084a31SMat Martineau 	new_frag->next = NULL;
651784084a31SMat Martineau 
651884084a31SMat Martineau 	(*last_frag)->next = new_frag;
651984084a31SMat Martineau 	*last_frag = new_frag;
652084084a31SMat Martineau 
652184084a31SMat Martineau 	skb->len += new_frag->len;
652284084a31SMat Martineau 	skb->data_len += new_frag->len;
652384084a31SMat Martineau 	skb->truesize += new_frag->truesize;
652484084a31SMat Martineau }
652584084a31SMat Martineau 
65264b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
65274b51dae9SMat Martineau 				struct l2cap_ctrl *control)
652884084a31SMat Martineau {
652984084a31SMat Martineau 	int err = -EINVAL;
65300a708f8fSGustavo F. Padovan 
65314b51dae9SMat Martineau 	switch (control->sar) {
65327e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
653384084a31SMat Martineau 		if (chan->sdu)
653484084a31SMat Martineau 			break;
65350a708f8fSGustavo F. Padovan 
653680b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
653784084a31SMat Martineau 		break;
65380a708f8fSGustavo F. Padovan 
65397e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
654084084a31SMat Martineau 		if (chan->sdu)
654184084a31SMat Martineau 			break;
65420a708f8fSGustavo F. Padovan 
6543dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
6544dbb50887SDaniel Borkmann 			break;
6545dbb50887SDaniel Borkmann 
65466f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
654703a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
65480a708f8fSGustavo F. Padovan 
654984084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
655084084a31SMat Martineau 			err = -EMSGSIZE;
655184084a31SMat Martineau 			break;
655284084a31SMat Martineau 		}
65530a708f8fSGustavo F. Padovan 
655484084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
655584084a31SMat Martineau 			break;
655684084a31SMat Martineau 
655784084a31SMat Martineau 		chan->sdu = skb;
655884084a31SMat Martineau 		chan->sdu_last_frag = skb;
655984084a31SMat Martineau 
656084084a31SMat Martineau 		skb = NULL;
656184084a31SMat Martineau 		err = 0;
65620a708f8fSGustavo F. Padovan 		break;
65630a708f8fSGustavo F. Padovan 
65647e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
65656f61fd47SGustavo F. Padovan 		if (!chan->sdu)
656684084a31SMat Martineau 			break;
65670a708f8fSGustavo F. Padovan 
656884084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
656984084a31SMat Martineau 				&chan->sdu_last_frag);
657084084a31SMat Martineau 		skb = NULL;
65710a708f8fSGustavo F. Padovan 
657284084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
657384084a31SMat Martineau 			break;
65740a708f8fSGustavo F. Padovan 
657584084a31SMat Martineau 		err = 0;
65760a708f8fSGustavo F. Padovan 		break;
65770a708f8fSGustavo F. Padovan 
65787e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
65796f61fd47SGustavo F. Padovan 		if (!chan->sdu)
658084084a31SMat Martineau 			break;
65810a708f8fSGustavo F. Padovan 
658284084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
658384084a31SMat Martineau 				&chan->sdu_last_frag);
658484084a31SMat Martineau 		skb = NULL;
65850a708f8fSGustavo F. Padovan 
658684084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
658784084a31SMat Martineau 			break;
65880a708f8fSGustavo F. Padovan 
658980b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
65900a708f8fSGustavo F. Padovan 
659184084a31SMat Martineau 		if (!err) {
659284084a31SMat Martineau 			/* Reassembly complete */
659384084a31SMat Martineau 			chan->sdu = NULL;
659484084a31SMat Martineau 			chan->sdu_last_frag = NULL;
659584084a31SMat Martineau 			chan->sdu_len = 0;
65960a708f8fSGustavo F. Padovan 		}
65970a708f8fSGustavo F. Padovan 		break;
65980a708f8fSGustavo F. Padovan 	}
65990a708f8fSGustavo F. Padovan 
660084084a31SMat Martineau 	if (err) {
66010a708f8fSGustavo F. Padovan 		kfree_skb(skb);
66026f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
66036f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
660484084a31SMat Martineau 		chan->sdu_last_frag = NULL;
660584084a31SMat Martineau 		chan->sdu_len = 0;
660684084a31SMat Martineau 	}
66070a708f8fSGustavo F. Padovan 
660884084a31SMat Martineau 	return err;
66090a708f8fSGustavo F. Padovan }
66100a708f8fSGustavo F. Padovan 
661132b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
661232b32735SMat Martineau {
661332b32735SMat Martineau 	/* Placeholder */
661432b32735SMat Martineau 	return 0;
661532b32735SMat Martineau }
661632b32735SMat Martineau 
6617e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
66180a708f8fSGustavo F. Padovan {
661961aa4f5bSMat Martineau 	u8 event;
662061aa4f5bSMat Martineau 
662161aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
662261aa4f5bSMat Martineau 		return;
662361aa4f5bSMat Martineau 
662461aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6625401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
66260a708f8fSGustavo F. Padovan }
66270a708f8fSGustavo F. Padovan 
6628d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6629d2a7ac5dSMat Martineau {
663063838725SMat Martineau 	int err = 0;
663163838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
663263838725SMat Martineau 	 * until a gap is encountered.
663363838725SMat Martineau 	 */
663463838725SMat Martineau 
663563838725SMat Martineau 	BT_DBG("chan %p", chan);
663663838725SMat Martineau 
663763838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
663863838725SMat Martineau 		struct sk_buff *skb;
663963838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
664063838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
664163838725SMat Martineau 
664263838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
664363838725SMat Martineau 
664463838725SMat Martineau 		if (!skb)
664563838725SMat Martineau 			break;
664663838725SMat Martineau 
664763838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
664863838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
6649a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
665063838725SMat Martineau 		if (err)
665163838725SMat Martineau 			break;
665263838725SMat Martineau 	}
665363838725SMat Martineau 
665463838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
665563838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
665663838725SMat Martineau 		l2cap_send_ack(chan);
665763838725SMat Martineau 	}
665863838725SMat Martineau 
665963838725SMat Martineau 	return err;
6660d2a7ac5dSMat Martineau }
6661d2a7ac5dSMat Martineau 
6662d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6663d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6664d2a7ac5dSMat Martineau {
6665f80842a8SMat Martineau 	struct sk_buff *skb;
6666f80842a8SMat Martineau 
6667f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6668f80842a8SMat Martineau 
6669f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6670f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
66715e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6672f80842a8SMat Martineau 		return;
6673f80842a8SMat Martineau 	}
6674f80842a8SMat Martineau 
6675f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6676f80842a8SMat Martineau 
6677f80842a8SMat Martineau 	if (skb == NULL) {
6678f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6679f80842a8SMat Martineau 		       control->reqseq);
6680f80842a8SMat Martineau 		return;
6681f80842a8SMat Martineau 	}
6682f80842a8SMat Martineau 
6683a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6684f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
66855e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6686f80842a8SMat Martineau 		return;
6687f80842a8SMat Martineau 	}
6688f80842a8SMat Martineau 
6689f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6690f80842a8SMat Martineau 
6691f80842a8SMat Martineau 	if (control->poll) {
6692f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6693f80842a8SMat Martineau 
6694f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6695f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6696f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6697f80842a8SMat Martineau 
6698f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6699f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6700f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6701f80842a8SMat Martineau 		}
6702f80842a8SMat Martineau 	} else {
6703f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6704f80842a8SMat Martineau 
6705f80842a8SMat Martineau 		if (control->final) {
6706f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6707f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6708f80842a8SMat Martineau 						&chan->conn_state))
6709f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6710f80842a8SMat Martineau 		} else {
6711f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6712f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6713f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6714f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6715f80842a8SMat Martineau 			}
6716f80842a8SMat Martineau 		}
6717f80842a8SMat Martineau 	}
6718d2a7ac5dSMat Martineau }
6719d2a7ac5dSMat Martineau 
6720d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6721d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6722d2a7ac5dSMat Martineau {
6723fcd289dfSMat Martineau 	struct sk_buff *skb;
6724fcd289dfSMat Martineau 
6725fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6726fcd289dfSMat Martineau 
6727fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6728fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
67295e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6730fcd289dfSMat Martineau 		return;
6731fcd289dfSMat Martineau 	}
6732fcd289dfSMat Martineau 
6733fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6734fcd289dfSMat Martineau 
6735fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6736a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6737fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
67385e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6739fcd289dfSMat Martineau 		return;
6740fcd289dfSMat Martineau 	}
6741fcd289dfSMat Martineau 
6742fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6743fcd289dfSMat Martineau 
6744fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6745fcd289dfSMat Martineau 
6746fcd289dfSMat Martineau 	if (control->final) {
6747fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6748fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6749fcd289dfSMat Martineau 	} else {
6750fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6751fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6752fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6753fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6754fcd289dfSMat Martineau 	}
6755d2a7ac5dSMat Martineau }
6756d2a7ac5dSMat Martineau 
67574b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
67584b51dae9SMat Martineau {
67594b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
67604b51dae9SMat Martineau 
67614b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
67624b51dae9SMat Martineau 	       chan->expected_tx_seq);
67634b51dae9SMat Martineau 
67644b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
67654b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
67664b51dae9SMat Martineau 		    chan->tx_win) {
67674b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
67684b51dae9SMat Martineau 			 * invalid packets.
67694b51dae9SMat Martineau 			 */
67704b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
67714b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
67724b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
67734b51dae9SMat Martineau 			} else {
67744b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
67754b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
67764b51dae9SMat Martineau 			}
67774b51dae9SMat Martineau 		}
67784b51dae9SMat Martineau 
67794b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
67804b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
67814b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
67824b51dae9SMat Martineau 		}
67834b51dae9SMat Martineau 
67844b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
67854b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
67864b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
67874b51dae9SMat Martineau 		}
67884b51dae9SMat Martineau 
67894b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
67904b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
67914b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
67924b51dae9SMat Martineau 		}
67934b51dae9SMat Martineau 	}
67944b51dae9SMat Martineau 
67954b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
67964b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
67974b51dae9SMat Martineau 		    chan->tx_win) {
67984b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
67994b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
68004b51dae9SMat Martineau 		} else {
68014b51dae9SMat Martineau 			BT_DBG("Expected");
68024b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
68034b51dae9SMat Martineau 		}
68044b51dae9SMat Martineau 	}
68054b51dae9SMat Martineau 
68064b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
68072d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
68084b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
68094b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
68104b51dae9SMat Martineau 	}
68114b51dae9SMat Martineau 
68124b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
68134b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
68144b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
68154b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
68164b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
68174b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
68184b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
68194b51dae9SMat Martineau 		 * request.
68204b51dae9SMat Martineau 		 *
68214b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
68224b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
68234b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
68244b51dae9SMat Martineau 		 *
68254b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
68264b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
68274b51dae9SMat Martineau 		 * causes a disconnect.
68284b51dae9SMat Martineau 		 */
68294b51dae9SMat Martineau 
68304b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
68314b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
68324b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
68334b51dae9SMat Martineau 		} else {
68344b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
68354b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
68364b51dae9SMat Martineau 		}
68374b51dae9SMat Martineau 	} else {
68384b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
68394b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
68404b51dae9SMat Martineau 	}
68414b51dae9SMat Martineau }
68424b51dae9SMat Martineau 
6843d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6844d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6845d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6846d2a7ac5dSMat Martineau {
6847d2a7ac5dSMat Martineau 	int err = 0;
6848941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6849d2a7ac5dSMat Martineau 
6850d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6851d2a7ac5dSMat Martineau 	       event);
6852d2a7ac5dSMat Martineau 
6853d2a7ac5dSMat Martineau 	switch (event) {
6854d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6855d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6856d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6857d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6858d2a7ac5dSMat Martineau 
6859d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6860d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6861d2a7ac5dSMat Martineau 				       control->txseq);
6862d2a7ac5dSMat Martineau 				break;
6863d2a7ac5dSMat Martineau 			}
6864d2a7ac5dSMat Martineau 
6865d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6866d2a7ac5dSMat Martineau 							   control->txseq);
6867d2a7ac5dSMat Martineau 
6868d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6869941247f9SPeter Senna Tschudin 			skb_in_use = true;
6870d2a7ac5dSMat Martineau 
6871d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6872d2a7ac5dSMat Martineau 			if (err)
6873d2a7ac5dSMat Martineau 				break;
6874d2a7ac5dSMat Martineau 
6875d2a7ac5dSMat Martineau 			if (control->final) {
6876d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6877d2a7ac5dSMat Martineau 							&chan->conn_state)) {
6878d2a7ac5dSMat Martineau 					control->final = 0;
6879d2a7ac5dSMat Martineau 					l2cap_retransmit_all(chan, control);
6880d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6881d2a7ac5dSMat Martineau 				}
6882d2a7ac5dSMat Martineau 			}
6883d2a7ac5dSMat Martineau 
6884d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6885d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6886d2a7ac5dSMat Martineau 			break;
6887d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6888d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6889d2a7ac5dSMat Martineau 
6890d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6891d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6892d2a7ac5dSMat Martineau 			 * when local busy is exited.
6893d2a7ac5dSMat Martineau 			 */
6894d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6895d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6896d2a7ac5dSMat Martineau 				       control->txseq);
6897d2a7ac5dSMat Martineau 				break;
6898d2a7ac5dSMat Martineau 			}
6899d2a7ac5dSMat Martineau 
6900d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
6901d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
6902d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
6903d2a7ac5dSMat Martineau 			 */
6904d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6905941247f9SPeter Senna Tschudin 			skb_in_use = true;
6906d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6907d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6908d2a7ac5dSMat Martineau 
6909d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
6910d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
6911d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
6912d2a7ac5dSMat Martineau 
6913d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
6914d2a7ac5dSMat Martineau 			break;
6915d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
6916d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6917d2a7ac5dSMat Martineau 			break;
6918d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
6919d2a7ac5dSMat Martineau 			break;
6920d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
6921d2a7ac5dSMat Martineau 		default:
69225e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
6923d2a7ac5dSMat Martineau 			break;
6924d2a7ac5dSMat Martineau 		}
6925d2a7ac5dSMat Martineau 		break;
6926d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
6927d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6928d2a7ac5dSMat Martineau 		if (control->final) {
6929d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6930d2a7ac5dSMat Martineau 
6931e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
6932e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
6933d2a7ac5dSMat Martineau 				control->final = 0;
6934d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
6935d2a7ac5dSMat Martineau 			}
6936d2a7ac5dSMat Martineau 
6937d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6938d2a7ac5dSMat Martineau 		} else if (control->poll) {
6939d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
6940d2a7ac5dSMat Martineau 		} else {
6941d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
6942d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
6943d2a7ac5dSMat Martineau 			    chan->unacked_frames)
6944d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
6945d2a7ac5dSMat Martineau 
6946d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
6947d2a7ac5dSMat Martineau 		}
6948d2a7ac5dSMat Martineau 		break;
6949d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
6950d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6951d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
6952d2a7ac5dSMat Martineau 		if (control && control->poll) {
6953d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
6954d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
6955d2a7ac5dSMat Martineau 		}
6956d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
6957d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
6958d2a7ac5dSMat Martineau 		break;
6959d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
6960d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
6961d2a7ac5dSMat Martineau 		break;
6962d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
6963d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
6964d2a7ac5dSMat Martineau 		break;
6965d2a7ac5dSMat Martineau 	default:
6966d2a7ac5dSMat Martineau 		break;
6967d2a7ac5dSMat Martineau 	}
6968d2a7ac5dSMat Martineau 
6969d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
6970d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
6971d2a7ac5dSMat Martineau 		kfree_skb(skb);
6972d2a7ac5dSMat Martineau 	}
6973d2a7ac5dSMat Martineau 
6974d2a7ac5dSMat Martineau 	return err;
6975d2a7ac5dSMat Martineau }
6976d2a7ac5dSMat Martineau 
6977d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
6978d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
6979d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
6980d2a7ac5dSMat Martineau {
6981d2a7ac5dSMat Martineau 	int err = 0;
6982d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
6983941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6984d2a7ac5dSMat Martineau 
6985d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6986d2a7ac5dSMat Martineau 	       event);
6987d2a7ac5dSMat Martineau 
6988d2a7ac5dSMat Martineau 	switch (event) {
6989d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6990d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
6991d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6992d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
6993d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6994d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
6995941247f9SPeter Senna Tschudin 			skb_in_use = true;
6996d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
6997d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
6998d2a7ac5dSMat Martineau 
6999d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
7000d2a7ac5dSMat Martineau 			break;
7001d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
7002d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
7003d2a7ac5dSMat Martineau 
7004d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7005d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7006941247f9SPeter Senna Tschudin 			skb_in_use = true;
7007d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7008d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7009d2a7ac5dSMat Martineau 
7010d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
7011d2a7ac5dSMat Martineau 			if (err)
7012d2a7ac5dSMat Martineau 				break;
7013d2a7ac5dSMat Martineau 
7014d2a7ac5dSMat Martineau 			break;
7015d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
7016d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
7017d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
7018d2a7ac5dSMat Martineau 			 * the missing frames.
7019d2a7ac5dSMat Martineau 			 */
7020d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7021941247f9SPeter Senna Tschudin 			skb_in_use = true;
7022d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7023d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7024d2a7ac5dSMat Martineau 
7025d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7026d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
7027d2a7ac5dSMat Martineau 			break;
7028d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
7029d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
7030d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
7031d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
7032d2a7ac5dSMat Martineau 			 * SREJ'd frames.
7033d2a7ac5dSMat Martineau 			 */
7034d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7035941247f9SPeter Senna Tschudin 			skb_in_use = true;
7036d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7037d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7038d2a7ac5dSMat Martineau 
7039d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7040d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
7041d2a7ac5dSMat Martineau 			break;
7042d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
7043d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
7044d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7045d2a7ac5dSMat Martineau 			break;
7046d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
7047d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
7048d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
7049d2a7ac5dSMat Martineau 			 */
7050d2a7ac5dSMat Martineau 			break;
7051d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
7052d2a7ac5dSMat Martineau 			break;
7053d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
7054d2a7ac5dSMat Martineau 		default:
70555e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7056d2a7ac5dSMat Martineau 			break;
7057d2a7ac5dSMat Martineau 		}
7058d2a7ac5dSMat Martineau 		break;
7059d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
7060d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7061d2a7ac5dSMat Martineau 		if (control->final) {
7062d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7063d2a7ac5dSMat Martineau 
7064d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
7065d2a7ac5dSMat Martineau 						&chan->conn_state)) {
7066d2a7ac5dSMat Martineau 				control->final = 0;
7067d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
7068d2a7ac5dSMat Martineau 			}
7069d2a7ac5dSMat Martineau 
7070d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
7071d2a7ac5dSMat Martineau 		} else if (control->poll) {
7072d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7073d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7074d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
7075d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7076d2a7ac5dSMat Martineau 			}
7077d2a7ac5dSMat Martineau 
7078d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
7079d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7080d2a7ac5dSMat Martineau 		} else {
7081d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7082d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7083d2a7ac5dSMat Martineau 			    chan->unacked_frames)
7084d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7085d2a7ac5dSMat Martineau 
7086d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
7087d2a7ac5dSMat Martineau 		}
7088d2a7ac5dSMat Martineau 		break;
7089d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
7090d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7091d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7092d2a7ac5dSMat Martineau 		if (control->poll) {
7093d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7094d2a7ac5dSMat Martineau 		} else {
7095d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
7096d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
7097d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
7098d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
7099d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
7100d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
7101d2a7ac5dSMat Martineau 		}
7102d2a7ac5dSMat Martineau 
7103d2a7ac5dSMat Martineau 		break;
7104d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
7105d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
7106d2a7ac5dSMat Martineau 		break;
7107d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
7108d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
7109d2a7ac5dSMat Martineau 		break;
7110d2a7ac5dSMat Martineau 	}
7111d2a7ac5dSMat Martineau 
7112d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
7113d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
7114d2a7ac5dSMat Martineau 		kfree_skb(skb);
7115d2a7ac5dSMat Martineau 	}
7116d2a7ac5dSMat Martineau 
7117d2a7ac5dSMat Martineau 	return err;
7118d2a7ac5dSMat Martineau }
7119d2a7ac5dSMat Martineau 
712032b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
712132b32735SMat Martineau {
712232b32735SMat Martineau 	BT_DBG("chan %p", chan);
712332b32735SMat Martineau 
712432b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
712532b32735SMat Martineau 
712632b32735SMat Martineau 	if (chan->hs_hcon)
712732b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
712832b32735SMat Martineau 	else
712932b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
713032b32735SMat Martineau 
713132b32735SMat Martineau 	return l2cap_resegment(chan);
713232b32735SMat Martineau }
713332b32735SMat Martineau 
713432b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
713532b32735SMat Martineau 				 struct l2cap_ctrl *control,
713632b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
713732b32735SMat Martineau {
713832b32735SMat Martineau 	int err;
713932b32735SMat Martineau 
714032b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
714132b32735SMat Martineau 	       event);
714232b32735SMat Martineau 
714332b32735SMat Martineau 	if (!control->poll)
714432b32735SMat Martineau 		return -EPROTO;
714532b32735SMat Martineau 
714632b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
714732b32735SMat Martineau 
714832b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
714932b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
715032b32735SMat Martineau 	else
715132b32735SMat Martineau 		chan->tx_send_head = NULL;
715232b32735SMat Martineau 
715332b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
715432b32735SMat Martineau 	 * by the receiver.
715532b32735SMat Martineau 	 */
715632b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
715732b32735SMat Martineau 	chan->unacked_frames = 0;
715832b32735SMat Martineau 
715932b32735SMat Martineau 	err = l2cap_finish_move(chan);
716032b32735SMat Martineau 	if (err)
716132b32735SMat Martineau 		return err;
716232b32735SMat Martineau 
716332b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
716432b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
716532b32735SMat Martineau 
716632b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
716732b32735SMat Martineau 		return -EPROTO;
716832b32735SMat Martineau 
716932b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
717032b32735SMat Martineau }
717132b32735SMat Martineau 
717232b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
717332b32735SMat Martineau 				 struct l2cap_ctrl *control,
717432b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
717532b32735SMat Martineau {
717632b32735SMat Martineau 	int err;
717732b32735SMat Martineau 
717832b32735SMat Martineau 	if (!control->final)
717932b32735SMat Martineau 		return -EPROTO;
718032b32735SMat Martineau 
718132b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
718232b32735SMat Martineau 
718332b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
718432b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
718532b32735SMat Martineau 
718632b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
718732b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
718832b32735SMat Martineau 	else
718932b32735SMat Martineau 		chan->tx_send_head = NULL;
719032b32735SMat Martineau 
719132b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
719232b32735SMat Martineau 	 * by the receiver.
719332b32735SMat Martineau 	 */
719432b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
719532b32735SMat Martineau 	chan->unacked_frames = 0;
719632b32735SMat Martineau 
719732b32735SMat Martineau 	if (chan->hs_hcon)
719832b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
719932b32735SMat Martineau 	else
720032b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
720132b32735SMat Martineau 
720232b32735SMat Martineau 	err = l2cap_resegment(chan);
720332b32735SMat Martineau 
720432b32735SMat Martineau 	if (!err)
720532b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
720632b32735SMat Martineau 
720732b32735SMat Martineau 	return err;
720832b32735SMat Martineau }
720932b32735SMat Martineau 
7210d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
7211d2a7ac5dSMat Martineau {
7212d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
7213d2a7ac5dSMat Martineau 	u16 unacked;
7214d2a7ac5dSMat Martineau 
7215d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
7216d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
7217d2a7ac5dSMat Martineau }
7218d2a7ac5dSMat Martineau 
7219cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7220cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
72210a708f8fSGustavo F. Padovan {
7222d2a7ac5dSMat Martineau 	int err = 0;
7223d2a7ac5dSMat Martineau 
7224d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
7225d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
7226d2a7ac5dSMat Martineau 
7227d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
7228d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
7229d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
7230d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
7231d2a7ac5dSMat Martineau 			break;
7232d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
7233d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
7234d2a7ac5dSMat Martineau 						       event);
7235d2a7ac5dSMat Martineau 			break;
723632b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
723732b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
723832b32735SMat Martineau 			break;
723932b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
724032b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
724132b32735SMat Martineau 			break;
7242d2a7ac5dSMat Martineau 		default:
7243d2a7ac5dSMat Martineau 			/* shut it down */
7244d2a7ac5dSMat Martineau 			break;
7245d2a7ac5dSMat Martineau 		}
7246d2a7ac5dSMat Martineau 	} else {
7247d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
7248d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
7249d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
72505e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
7251d2a7ac5dSMat Martineau 	}
7252d2a7ac5dSMat Martineau 
7253d2a7ac5dSMat Martineau 	return err;
7254cec8ab6eSMat Martineau }
7255cec8ab6eSMat Martineau 
7256cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7257cec8ab6eSMat Martineau 			   struct sk_buff *skb)
7258cec8ab6eSMat Martineau {
72594b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
72604b51dae9SMat Martineau 	       chan->rx_state);
72614b51dae9SMat Martineau 
72624b51dae9SMat Martineau 	if (l2cap_classify_txseq(chan, control->txseq) ==
72634b51dae9SMat Martineau 	    L2CAP_TXSEQ_EXPECTED) {
72644b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
72654b51dae9SMat Martineau 
72664b51dae9SMat Martineau 		BT_DBG("buffer_seq %d->%d", chan->buffer_seq,
72674b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
72684b51dae9SMat Martineau 
72694b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
72704b51dae9SMat Martineau 
72714b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
72724b51dae9SMat Martineau 	} else {
72734b51dae9SMat Martineau 		if (chan->sdu) {
72744b51dae9SMat Martineau 			kfree_skb(chan->sdu);
72754b51dae9SMat Martineau 			chan->sdu = NULL;
72764b51dae9SMat Martineau 		}
72774b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
72784b51dae9SMat Martineau 		chan->sdu_len = 0;
72794b51dae9SMat Martineau 
72804b51dae9SMat Martineau 		if (skb) {
72814b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
72824b51dae9SMat Martineau 			kfree_skb(skb);
72834b51dae9SMat Martineau 		}
72844b51dae9SMat Martineau 	}
72854b51dae9SMat Martineau 
72864b51dae9SMat Martineau 	chan->last_acked_seq = control->txseq;
72874b51dae9SMat Martineau 	chan->expected_tx_seq = __next_seq(chan, control->txseq);
72884b51dae9SMat Martineau 
72899a544210SPrasanna Karthik 	return 0;
7290cec8ab6eSMat Martineau }
7291cec8ab6eSMat Martineau 
7292cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7293cec8ab6eSMat Martineau {
7294a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
7295cec8ab6eSMat Martineau 	u16 len;
7296cec8ab6eSMat Martineau 	u8 event;
72970a708f8fSGustavo F. Padovan 
7298b76bbd66SMat Martineau 	__unpack_control(chan, skb);
7299b76bbd66SMat Martineau 
73000a708f8fSGustavo F. Padovan 	len = skb->len;
73010a708f8fSGustavo F. Padovan 
73020a708f8fSGustavo F. Padovan 	/*
73030a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
73040a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
7305cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
73060a708f8fSGustavo F. Padovan 	 */
730747d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
73080a708f8fSGustavo F. Padovan 		goto drop;
73090a708f8fSGustavo F. Padovan 
7310cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
731103a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
73120a708f8fSGustavo F. Padovan 
731347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
731403a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
73150a708f8fSGustavo F. Padovan 
731647d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
73175e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
73180a708f8fSGustavo F. Padovan 		goto drop;
73190a708f8fSGustavo F. Padovan 	}
73200a708f8fSGustavo F. Padovan 
7321f1942564SLuiz Augusto von Dentz 	if (chan->ops->filter) {
7322f1942564SLuiz Augusto von Dentz 		if (chan->ops->filter(chan, skb))
7323dbb50887SDaniel Borkmann 			goto drop;
7324f1942564SLuiz Augusto von Dentz 	}
7325dbb50887SDaniel Borkmann 
7326cec8ab6eSMat Martineau 	if (!control->sframe) {
7327cec8ab6eSMat Martineau 		int err;
73280a708f8fSGustavo F. Padovan 
7329cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
7330cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
7331cec8ab6eSMat Martineau 		       control->txseq);
7332836be934SAndrei Emeltchenko 
7333cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
7334cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
7335cec8ab6eSMat Martineau 		 */
7336cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
73370a708f8fSGustavo F. Padovan 			goto drop;
73380a708f8fSGustavo F. Padovan 
7339cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
7340cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
7341cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
73420a708f8fSGustavo F. Padovan 		} else {
7343cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
7344cec8ab6eSMat Martineau 		}
7345cec8ab6eSMat Martineau 
7346cec8ab6eSMat Martineau 		if (err)
73475e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7348cec8ab6eSMat Martineau 	} else {
7349cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
7350cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
7351cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
7352cec8ab6eSMat Martineau 		};
7353cec8ab6eSMat Martineau 
7354cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
7355cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
7356cec8ab6eSMat Martineau 			goto drop;
7357cec8ab6eSMat Martineau 
7358cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
7359cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
7360cec8ab6eSMat Martineau 		       control->super);
7361cec8ab6eSMat Martineau 
73620a708f8fSGustavo F. Padovan 		if (len != 0) {
73631bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
73645e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
73650a708f8fSGustavo F. Padovan 			goto drop;
73660a708f8fSGustavo F. Padovan 		}
73670a708f8fSGustavo F. Padovan 
7368cec8ab6eSMat Martineau 		/* Validate F and P bits */
7369cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
7370cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
7371cec8ab6eSMat Martineau 			goto drop;
7372cec8ab6eSMat Martineau 
7373cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
7374cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
73755e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
73760a708f8fSGustavo F. Padovan 	}
73770a708f8fSGustavo F. Padovan 
73780a708f8fSGustavo F. Padovan 	return 0;
73790a708f8fSGustavo F. Padovan 
73800a708f8fSGustavo F. Padovan drop:
73810a708f8fSGustavo F. Padovan 	kfree_skb(skb);
73820a708f8fSGustavo F. Padovan 	return 0;
73830a708f8fSGustavo F. Padovan }
73840a708f8fSGustavo F. Padovan 
7385b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
7386b1c325c2SJohan Hedberg {
7387b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
7388b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
7389b1c325c2SJohan Hedberg 	u16 return_credits;
7390b1c325c2SJohan Hedberg 
739115f02b91SLuiz Augusto von Dentz 	return_credits = (chan->imtu / chan->mps) + 1;
7392b1c325c2SJohan Hedberg 
739315f02b91SLuiz Augusto von Dentz 	if (chan->rx_credits >= return_credits)
739496cd8eaaSLuiz Augusto von Dentz 		return;
7395b1c325c2SJohan Hedberg 
739615f02b91SLuiz Augusto von Dentz 	return_credits -= chan->rx_credits;
739715f02b91SLuiz Augusto von Dentz 
7398b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
7399b1c325c2SJohan Hedberg 
7400b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
7401b1c325c2SJohan Hedberg 
7402b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
7403b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
7404b1c325c2SJohan Hedberg 
7405b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
7406b1c325c2SJohan Hedberg 
7407b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
7408b1c325c2SJohan Hedberg }
7409b1c325c2SJohan Hedberg 
741015f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
741196cd8eaaSLuiz Augusto von Dentz {
741296cd8eaaSLuiz Augusto von Dentz 	int err;
741396cd8eaaSLuiz Augusto von Dentz 
741496cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
741596cd8eaaSLuiz Augusto von Dentz 
741696cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
741796cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
741896cd8eaaSLuiz Augusto von Dentz 
741996cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
742096cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
742196cd8eaaSLuiz Augusto von Dentz 
742296cd8eaaSLuiz Augusto von Dentz 	return err;
742396cd8eaaSLuiz Augusto von Dentz }
742496cd8eaaSLuiz Augusto von Dentz 
742515f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7426fad5fc89SJohan Hedberg {
7427aac23bf6SJohan Hedberg 	int err;
7428fad5fc89SJohan Hedberg 
7429aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
7430aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
7431dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
7432fad5fc89SJohan Hedberg 		return -ENOBUFS;
7433aac23bf6SJohan Hedberg 	}
7434aac23bf6SJohan Hedberg 
7435aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
7436aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
7437aac23bf6SJohan Hedberg 		return -ENOBUFS;
7438aac23bf6SJohan Hedberg 	}
7439fad5fc89SJohan Hedberg 
7440fad5fc89SJohan Hedberg 	chan->rx_credits--;
7441fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
7442fad5fc89SJohan Hedberg 
744396cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
744496cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
744596cd8eaaSLuiz Augusto von Dentz 	 */
744696cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
7447fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
7448fad5fc89SJohan Hedberg 
7449aac23bf6SJohan Hedberg 	err = 0;
7450aac23bf6SJohan Hedberg 
7451aac23bf6SJohan Hedberg 	if (!chan->sdu) {
7452aac23bf6SJohan Hedberg 		u16 sdu_len;
7453aac23bf6SJohan Hedberg 
7454aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
7455aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
7456aac23bf6SJohan Hedberg 
7457aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
7458aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
7459aac23bf6SJohan Hedberg 
7460aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
7461aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
7462aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
7463aac23bf6SJohan Hedberg 			goto failed;
7464aac23bf6SJohan Hedberg 		}
7465aac23bf6SJohan Hedberg 
7466aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
7467aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
7468aac23bf6SJohan Hedberg 			err = -EINVAL;
7469aac23bf6SJohan Hedberg 			goto failed;
7470aac23bf6SJohan Hedberg 		}
7471aac23bf6SJohan Hedberg 
7472aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
747315f02b91SLuiz Augusto von Dentz 			return l2cap_ecred_recv(chan, skb);
7474aac23bf6SJohan Hedberg 
7475aac23bf6SJohan Hedberg 		chan->sdu = skb;
7476aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
7477aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
7478aac23bf6SJohan Hedberg 
7479a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
7480a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
7481a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
7482a5c3021bSLuiz Augusto von Dentz 
7483a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
7484a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
7485a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
7486a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
7487a5c3021bSLuiz Augusto von Dentz 		}
7488a5c3021bSLuiz Augusto von Dentz 
7489aac23bf6SJohan Hedberg 		return 0;
7490aac23bf6SJohan Hedberg 	}
7491aac23bf6SJohan Hedberg 
7492aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
7493aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
7494aac23bf6SJohan Hedberg 
7495aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
7496aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
7497aac23bf6SJohan Hedberg 		err = -EINVAL;
7498aac23bf6SJohan Hedberg 		goto failed;
7499aac23bf6SJohan Hedberg 	}
7500aac23bf6SJohan Hedberg 
7501aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
7502aac23bf6SJohan Hedberg 	skb = NULL;
7503aac23bf6SJohan Hedberg 
7504aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
750515f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_recv(chan, chan->sdu);
7506aac23bf6SJohan Hedberg 		if (!err) {
7507aac23bf6SJohan Hedberg 			chan->sdu = NULL;
7508aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
7509aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
7510aac23bf6SJohan Hedberg 		}
7511aac23bf6SJohan Hedberg 	}
7512aac23bf6SJohan Hedberg 
7513aac23bf6SJohan Hedberg failed:
7514aac23bf6SJohan Hedberg 	if (err) {
7515aac23bf6SJohan Hedberg 		kfree_skb(skb);
7516aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
7517aac23bf6SJohan Hedberg 		chan->sdu = NULL;
7518aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
7519aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
7520aac23bf6SJohan Hedberg 	}
7521aac23bf6SJohan Hedberg 
7522aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
7523aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
7524aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
7525aac23bf6SJohan Hedberg 	 */
7526aac23bf6SJohan Hedberg 	return 0;
7527fad5fc89SJohan Hedberg }
7528fad5fc89SJohan Hedberg 
752913ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
753013ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
75310a708f8fSGustavo F. Padovan {
753248454079SGustavo F. Padovan 	struct l2cap_chan *chan;
75330a708f8fSGustavo F. Padovan 
7534baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
753548454079SGustavo F. Padovan 	if (!chan) {
753697e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
753797e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
753897e8e89dSAndrei Emeltchenko 			if (!chan) {
753997e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
754013ca56e0SAndrei Emeltchenko 				return;
754197e8e89dSAndrei Emeltchenko 			}
754297e8e89dSAndrei Emeltchenko 
754397e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
754497e8e89dSAndrei Emeltchenko 		} else {
75450a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
75466be36555SAndrei Emeltchenko 			/* Drop packet and return */
75473379013bSDan Carpenter 			kfree_skb(skb);
754813ca56e0SAndrei Emeltchenko 			return;
75490a708f8fSGustavo F. Padovan 		}
755097e8e89dSAndrei Emeltchenko 	}
75510a708f8fSGustavo F. Padovan 
755249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
75530a708f8fSGustavo F. Padovan 
7554315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
7555315917e0SJohan Hedberg 	 * procdure is done simply assume that the channel is supported
7556315917e0SJohan Hedberg 	 * and mark it as ready.
7557315917e0SJohan Hedberg 	 */
7558315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
7559315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
7560315917e0SJohan Hedberg 
756189bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
75620a708f8fSGustavo F. Padovan 		goto drop;
75630a708f8fSGustavo F. Padovan 
75640c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
756538319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
756615f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
756715f02b91SLuiz Augusto von Dentz 		if (l2cap_ecred_data_rcv(chan, skb) < 0)
7568fad5fc89SJohan Hedberg 			goto drop;
7569fad5fc89SJohan Hedberg 
7570fad5fc89SJohan Hedberg 		goto done;
7571fad5fc89SJohan Hedberg 
75720a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
75730a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
75740a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
75750a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
75760a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
75770a708f8fSGustavo F. Padovan 
75782c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
75792c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
75800a708f8fSGustavo F. Padovan 			goto drop;
75812c96e03dSSzymon Janc 		}
75820a708f8fSGustavo F. Padovan 
758380b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
75840a708f8fSGustavo F. Padovan 			goto done;
75850a708f8fSGustavo F. Padovan 		break;
75860a708f8fSGustavo F. Padovan 
75870a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
75880a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
7589cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
75900a708f8fSGustavo F. Padovan 		goto done;
75910a708f8fSGustavo F. Padovan 
75920a708f8fSGustavo F. Padovan 	default:
75930c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
75940a708f8fSGustavo F. Padovan 		break;
75950a708f8fSGustavo F. Padovan 	}
75960a708f8fSGustavo F. Padovan 
75970a708f8fSGustavo F. Padovan drop:
75980a708f8fSGustavo F. Padovan 	kfree_skb(skb);
75990a708f8fSGustavo F. Padovan 
76000a708f8fSGustavo F. Padovan done:
76016be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
76020a708f8fSGustavo F. Padovan }
76030a708f8fSGustavo F. Padovan 
760484104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
760584104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
76060a708f8fSGustavo F. Padovan {
7607ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
760823691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
76090a708f8fSGustavo F. Padovan 
7610ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
7611a24cce14SJohan Hedberg 		goto free_skb;
7612ae4fd2d3SMarcel Holtmann 
7613bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
7614bf20fd4eSJohan Hedberg 					ACL_LINK);
761523691d75SGustavo F. Padovan 	if (!chan)
7616a24cce14SJohan Hedberg 		goto free_skb;
76170a708f8fSGustavo F. Padovan 
76185b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
76190a708f8fSGustavo F. Padovan 
762089bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
76210a708f8fSGustavo F. Padovan 		goto drop;
76220a708f8fSGustavo F. Padovan 
7623e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
76240a708f8fSGustavo F. Padovan 		goto drop;
76250a708f8fSGustavo F. Padovan 
76262edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
7627a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
7628a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
76292edf870dSMarcel Holtmann 
7630a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
7631a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
763284104b24SAndrei Emeltchenko 		return;
7633a24cce14SJohan Hedberg 	}
76340a708f8fSGustavo F. Padovan 
76350a708f8fSGustavo F. Padovan drop:
7636a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
7637a24cce14SJohan Hedberg free_skb:
76380a708f8fSGustavo F. Padovan 	kfree_skb(skb);
76390a708f8fSGustavo F. Padovan }
76400a708f8fSGustavo F. Padovan 
76410a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
76420a708f8fSGustavo F. Padovan {
76430a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
764461a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
76450a708f8fSGustavo F. Padovan 	u16 cid, len;
76460a708f8fSGustavo F. Padovan 	__le16 psm;
76470a708f8fSGustavo F. Padovan 
764861a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
764961a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
765061a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
765161a939c6SJohan Hedberg 		return;
765261a939c6SJohan Hedberg 	}
765361a939c6SJohan Hedberg 
76540a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
76550a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
76560a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
76570a708f8fSGustavo F. Padovan 
76580a708f8fSGustavo F. Padovan 	if (len != skb->len) {
76590a708f8fSGustavo F. Padovan 		kfree_skb(skb);
76600a708f8fSGustavo F. Padovan 		return;
76610a708f8fSGustavo F. Padovan 	}
76620a708f8fSGustavo F. Padovan 
76639e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
76649e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
76659e1d7e15SJohan Hedberg 	 */
76669e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
7667dcc36c16SJohan Hedberg 	    hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst,
7668a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
7669e493150eSJohan Hedberg 		kfree_skb(skb);
7670e493150eSJohan Hedberg 		return;
7671e493150eSJohan Hedberg 	}
7672e493150eSJohan Hedberg 
76730a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
76740a708f8fSGustavo F. Padovan 
76750a708f8fSGustavo F. Padovan 	switch (cid) {
76760a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
76770a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
76780a708f8fSGustavo F. Padovan 		break;
76790a708f8fSGustavo F. Padovan 
76800a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7681097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
76820181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
76830a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
76840a708f8fSGustavo F. Padovan 		break;
76850a708f8fSGustavo F. Padovan 
7686a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7687a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7688a2877629SMarcel Holtmann 		break;
7689a2877629SMarcel Holtmann 
76900a708f8fSGustavo F. Padovan 	default:
76910a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
76920a708f8fSGustavo F. Padovan 		break;
76930a708f8fSGustavo F. Padovan 	}
76940a708f8fSGustavo F. Padovan }
76950a708f8fSGustavo F. Padovan 
769661a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
769761a939c6SJohan Hedberg {
769861a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
769961a939c6SJohan Hedberg 					       pending_rx_work);
770061a939c6SJohan Hedberg 	struct sk_buff *skb;
770161a939c6SJohan Hedberg 
770261a939c6SJohan Hedberg 	BT_DBG("");
770361a939c6SJohan Hedberg 
770461a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
770561a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
770661a939c6SJohan Hedberg }
770761a939c6SJohan Hedberg 
7708162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
7709162b49e7SJohan Hedberg {
7710162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
7711162b49e7SJohan Hedberg 	struct hci_chan *hchan;
7712162b49e7SJohan Hedberg 
7713162b49e7SJohan Hedberg 	if (conn)
7714162b49e7SJohan Hedberg 		return conn;
7715162b49e7SJohan Hedberg 
7716162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
7717162b49e7SJohan Hedberg 	if (!hchan)
7718162b49e7SJohan Hedberg 		return NULL;
7719162b49e7SJohan Hedberg 
772027f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
7721162b49e7SJohan Hedberg 	if (!conn) {
7722162b49e7SJohan Hedberg 		hci_chan_del(hchan);
7723162b49e7SJohan Hedberg 		return NULL;
7724162b49e7SJohan Hedberg 	}
7725162b49e7SJohan Hedberg 
7726162b49e7SJohan Hedberg 	kref_init(&conn->ref);
7727162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
772851bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
7729162b49e7SJohan Hedberg 	conn->hchan = hchan;
7730162b49e7SJohan Hedberg 
7731162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
7732162b49e7SJohan Hedberg 
7733162b49e7SJohan Hedberg 	switch (hcon->type) {
7734162b49e7SJohan Hedberg 	case LE_LINK:
7735162b49e7SJohan Hedberg 		if (hcon->hdev->le_mtu) {
7736162b49e7SJohan Hedberg 			conn->mtu = hcon->hdev->le_mtu;
7737162b49e7SJohan Hedberg 			break;
7738162b49e7SJohan Hedberg 		}
773919186c7bSGustavo A. R. Silva 		fallthrough;
7740162b49e7SJohan Hedberg 	default:
7741162b49e7SJohan Hedberg 		conn->mtu = hcon->hdev->acl_mtu;
7742162b49e7SJohan Hedberg 		break;
7743162b49e7SJohan Hedberg 	}
7744162b49e7SJohan Hedberg 
7745162b49e7SJohan Hedberg 	conn->feat_mask = 0;
7746162b49e7SJohan Hedberg 
77470bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
77480bd49fc7SJohan Hedberg 
77490bd49fc7SJohan Hedberg 	if (hcon->type == ACL_LINK &&
7750d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
77510bd49fc7SJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_A2MP;
7752162b49e7SJohan Hedberg 
7753d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
7754f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
7755b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
7756b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
7757b5ae344dSJohan Hedberg 
77585a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
7759162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
7760162b49e7SJohan Hedberg 
7761162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
7762162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
7763162b49e7SJohan Hedberg 
7764162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
7765162b49e7SJohan Hedberg 
776661a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
776761a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
7768f3d82d0cSJohan Hedberg 	INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr);
776961a939c6SJohan Hedberg 
7770162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
7771162b49e7SJohan Hedberg 
7772162b49e7SJohan Hedberg 	return conn;
7773162b49e7SJohan Hedberg }
7774162b49e7SJohan Hedberg 
7775162b49e7SJohan Hedberg static bool is_valid_psm(u16 psm, u8 dst_type) {
7776162b49e7SJohan Hedberg 	if (!psm)
7777162b49e7SJohan Hedberg 		return false;
7778162b49e7SJohan Hedberg 
7779162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
7780162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
7781162b49e7SJohan Hedberg 
7782162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
7783162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
7784162b49e7SJohan Hedberg }
7785162b49e7SJohan Hedberg 
7786da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
7787da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
7788da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7789da49b602SLuiz Augusto von Dentz 	int count;
7790da49b602SLuiz Augusto von Dentz };
7791da49b602SLuiz Augusto von Dentz 
7792da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
7793da49b602SLuiz Augusto von Dentz {
7794da49b602SLuiz Augusto von Dentz 	struct l2cap_chan_data *d = data;
7795da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7796da49b602SLuiz Augusto von Dentz 
7797da49b602SLuiz Augusto von Dentz 	if (chan == d->chan)
7798da49b602SLuiz Augusto von Dentz 		return;
7799da49b602SLuiz Augusto von Dentz 
7800da49b602SLuiz Augusto von Dentz 	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
7801da49b602SLuiz Augusto von Dentz 		return;
7802da49b602SLuiz Augusto von Dentz 
7803da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
7804da49b602SLuiz Augusto von Dentz 
7805da49b602SLuiz Augusto von Dentz 	/* Only count deferred channels with the same PID/PSM */
7806da49b602SLuiz Augusto von Dentz 	if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
7807da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
7808da49b602SLuiz Augusto von Dentz 		return;
7809da49b602SLuiz Augusto von Dentz 
7810da49b602SLuiz Augusto von Dentz 	d->count++;
7811da49b602SLuiz Augusto von Dentz }
7812da49b602SLuiz Augusto von Dentz 
7813162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7814162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
7815162b49e7SJohan Hedberg {
7816162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
7817162b49e7SJohan Hedberg 	struct hci_conn *hcon;
7818162b49e7SJohan Hedberg 	struct hci_dev *hdev;
7819162b49e7SJohan Hedberg 	int err;
7820162b49e7SJohan Hedberg 
782115f02b91SLuiz Augusto von Dentz 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
782215f02b91SLuiz Augusto von Dentz 	       dst, dst_type, __le16_to_cpu(psm), chan->mode);
7823162b49e7SJohan Hedberg 
782439385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
7825162b49e7SJohan Hedberg 	if (!hdev)
7826162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
7827162b49e7SJohan Hedberg 
7828162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
7829162b49e7SJohan Hedberg 
7830162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
7831162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
7832162b49e7SJohan Hedberg 		err = -EINVAL;
7833162b49e7SJohan Hedberg 		goto done;
7834162b49e7SJohan Hedberg 	}
7835162b49e7SJohan Hedberg 
783621626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
783721626e62SJohan Hedberg 		err = -EINVAL;
783821626e62SJohan Hedberg 		goto done;
783921626e62SJohan Hedberg 	}
784021626e62SJohan Hedberg 
784121626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
7842162b49e7SJohan Hedberg 		err = -EINVAL;
7843162b49e7SJohan Hedberg 		goto done;
7844162b49e7SJohan Hedberg 	}
7845162b49e7SJohan Hedberg 
7846162b49e7SJohan Hedberg 	switch (chan->mode) {
7847162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
7848162b49e7SJohan Hedberg 		break;
7849162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
78504be5ca67SLuiz Augusto von Dentz 		break;
785115f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
78524be5ca67SLuiz Augusto von Dentz 		if (!enable_ecred) {
78534be5ca67SLuiz Augusto von Dentz 			err = -EOPNOTSUPP;
78544be5ca67SLuiz Augusto von Dentz 			goto done;
78554be5ca67SLuiz Augusto von Dentz 		}
7856162b49e7SJohan Hedberg 		break;
7857162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
7858162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
7859162b49e7SJohan Hedberg 		if (!disable_ertm)
7860162b49e7SJohan Hedberg 			break;
786119186c7bSGustavo A. R. Silva 		fallthrough;
7862162b49e7SJohan Hedberg 	default:
7863beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
7864162b49e7SJohan Hedberg 		goto done;
7865162b49e7SJohan Hedberg 	}
7866162b49e7SJohan Hedberg 
7867162b49e7SJohan Hedberg 	switch (chan->state) {
7868162b49e7SJohan Hedberg 	case BT_CONNECT:
7869162b49e7SJohan Hedberg 	case BT_CONNECT2:
7870162b49e7SJohan Hedberg 	case BT_CONFIG:
7871162b49e7SJohan Hedberg 		/* Already connecting */
7872162b49e7SJohan Hedberg 		err = 0;
7873162b49e7SJohan Hedberg 		goto done;
7874162b49e7SJohan Hedberg 
7875162b49e7SJohan Hedberg 	case BT_CONNECTED:
7876162b49e7SJohan Hedberg 		/* Already connected */
7877162b49e7SJohan Hedberg 		err = -EISCONN;
7878162b49e7SJohan Hedberg 		goto done;
7879162b49e7SJohan Hedberg 
7880162b49e7SJohan Hedberg 	case BT_OPEN:
7881162b49e7SJohan Hedberg 	case BT_BOUND:
7882162b49e7SJohan Hedberg 		/* Can connect */
7883162b49e7SJohan Hedberg 		break;
7884162b49e7SJohan Hedberg 
7885162b49e7SJohan Hedberg 	default:
7886162b49e7SJohan Hedberg 		err = -EBADFD;
7887162b49e7SJohan Hedberg 		goto done;
7888162b49e7SJohan Hedberg 	}
7889162b49e7SJohan Hedberg 
7890162b49e7SJohan Hedberg 	/* Set destination address and psm */
7891162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
7892162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
7893162b49e7SJohan Hedberg 
7894162b49e7SJohan Hedberg 	chan->psm = psm;
7895162b49e7SJohan Hedberg 	chan->dcid = cid;
7896162b49e7SJohan Hedberg 
78976f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
78986f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
78996f77d8c7SAndre Guedes 		 */
79006f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
79016f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
79026f77d8c7SAndre Guedes 		else
79036f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
79046f77d8c7SAndre Guedes 
7905d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
79060ad06aa6SJohan Hedberg 			hcon = hci_connect_le(hdev, dst, dst_type,
7907fa142220SJakub Pawlowski 					      chan->sec_level,
7908fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
7909082f2300SSzymon Janc 					      HCI_ROLE_SLAVE, NULL);
79100ad06aa6SJohan Hedberg 		else
79110ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
79120ad06aa6SJohan Hedberg 						   chan->sec_level,
791376b13996SManish Mandlik 						   HCI_LE_CONN_TIMEOUT,
791476b13996SManish Mandlik 						   CONN_REASON_L2CAP_CHAN);
79150ad06aa6SJohan Hedberg 
79166f77d8c7SAndre Guedes 	} else {
7917d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
791876b13996SManish Mandlik 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
791976b13996SManish Mandlik 				       CONN_REASON_L2CAP_CHAN);
79206f77d8c7SAndre Guedes 	}
7921162b49e7SJohan Hedberg 
7922162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
7923162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
7924162b49e7SJohan Hedberg 		goto done;
7925162b49e7SJohan Hedberg 	}
7926162b49e7SJohan Hedberg 
7927162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
7928162b49e7SJohan Hedberg 	if (!conn) {
7929162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7930162b49e7SJohan Hedberg 		err = -ENOMEM;
7931162b49e7SJohan Hedberg 		goto done;
7932162b49e7SJohan Hedberg 	}
7933162b49e7SJohan Hedberg 
7934da49b602SLuiz Augusto von Dentz 	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
7935da49b602SLuiz Augusto von Dentz 		struct l2cap_chan_data data;
7936da49b602SLuiz Augusto von Dentz 
7937da49b602SLuiz Augusto von Dentz 		data.chan = chan;
7938da49b602SLuiz Augusto von Dentz 		data.pid = chan->ops->get_peer_pid(chan);
7939da49b602SLuiz Augusto von Dentz 		data.count = 1;
7940da49b602SLuiz Augusto von Dentz 
7941da49b602SLuiz Augusto von Dentz 		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
7942da49b602SLuiz Augusto von Dentz 
7943da49b602SLuiz Augusto von Dentz 		/* Check if there isn't too many channels being connected */
7944da49b602SLuiz Augusto von Dentz 		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
7945da49b602SLuiz Augusto von Dentz 			hci_conn_drop(hcon);
7946da49b602SLuiz Augusto von Dentz 			err = -EPROTO;
7947da49b602SLuiz Augusto von Dentz 			goto done;
7948da49b602SLuiz Augusto von Dentz 		}
7949da49b602SLuiz Augusto von Dentz 	}
7950da49b602SLuiz Augusto von Dentz 
795102e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
795202e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
795302e246aeSJohan Hedberg 
7954162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
7955162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
7956162b49e7SJohan Hedberg 		err = -EBUSY;
795702e246aeSJohan Hedberg 		goto chan_unlock;
7958162b49e7SJohan Hedberg 	}
7959162b49e7SJohan Hedberg 
7960162b49e7SJohan Hedberg 	/* Update source addr of the socket */
7961162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
7962a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
7963162b49e7SJohan Hedberg 
796402e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
7965162b49e7SJohan Hedberg 
7966162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
7967162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
7968162b49e7SJohan Hedberg 
7969162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
7970162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
7971162b49e7SJohan Hedberg 
797261202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
797361202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
797461202e4dSJohan Hedberg 	 */
797561202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
797661202e4dSJohan Hedberg 	chan->sport = 0;
797761202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
797861202e4dSJohan Hedberg 
7979162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
7980162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
7981162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
7982e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
7983162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
7984162b49e7SJohan Hedberg 		} else
7985162b49e7SJohan Hedberg 			l2cap_do_start(chan);
7986162b49e7SJohan Hedberg 	}
7987162b49e7SJohan Hedberg 
7988162b49e7SJohan Hedberg 	err = 0;
7989162b49e7SJohan Hedberg 
799002e246aeSJohan Hedberg chan_unlock:
7991162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
799202e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
799302e246aeSJohan Hedberg done:
7994162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
7995162b49e7SJohan Hedberg 	hci_dev_put(hdev);
7996162b49e7SJohan Hedberg 	return err;
7997162b49e7SJohan Hedberg }
79986b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
7999162b49e7SJohan Hedberg 
800015f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
800115f02b91SLuiz Augusto von Dentz {
800215f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
800315f02b91SLuiz Augusto von Dentz 	struct {
800415f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_reconf_req req;
800515f02b91SLuiz Augusto von Dentz 		__le16 scid;
800615f02b91SLuiz Augusto von Dentz 	} pdu;
800715f02b91SLuiz Augusto von Dentz 
800815f02b91SLuiz Augusto von Dentz 	pdu.req.mtu = cpu_to_le16(chan->imtu);
800915f02b91SLuiz Augusto von Dentz 	pdu.req.mps = cpu_to_le16(chan->mps);
801015f02b91SLuiz Augusto von Dentz 	pdu.scid    = cpu_to_le16(chan->scid);
801115f02b91SLuiz Augusto von Dentz 
801215f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
801315f02b91SLuiz Augusto von Dentz 
801415f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
801515f02b91SLuiz Augusto von Dentz 		       sizeof(pdu), &pdu);
801615f02b91SLuiz Augusto von Dentz }
801715f02b91SLuiz Augusto von Dentz 
801815f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
801915f02b91SLuiz Augusto von Dentz {
802015f02b91SLuiz Augusto von Dentz 	if (chan->imtu > mtu)
802115f02b91SLuiz Augusto von Dentz 		return -EINVAL;
802215f02b91SLuiz Augusto von Dentz 
802315f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
802415f02b91SLuiz Augusto von Dentz 
802515f02b91SLuiz Augusto von Dentz 	chan->imtu = mtu;
802615f02b91SLuiz Augusto von Dentz 
802715f02b91SLuiz Augusto von Dentz 	l2cap_ecred_reconfigure(chan);
802815f02b91SLuiz Augusto von Dentz 
802915f02b91SLuiz Augusto von Dentz 	return 0;
803015f02b91SLuiz Augusto von Dentz }
803115f02b91SLuiz Augusto von Dentz 
80320a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
80330a708f8fSGustavo F. Padovan 
8034686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
80350a708f8fSGustavo F. Padovan {
80360a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
803723691d75SGustavo F. Padovan 	struct l2cap_chan *c;
80380a708f8fSGustavo F. Padovan 
80396ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
80400a708f8fSGustavo F. Padovan 
80410a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
804223691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
804323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
804489bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
80450a708f8fSGustavo F. Padovan 			continue;
80460a708f8fSGustavo F. Padovan 
80477eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
80480a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
804943bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
80500a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
80510a708f8fSGustavo F. Padovan 			exact++;
80527eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
80530a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
805443bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
80550a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
80560a708f8fSGustavo F. Padovan 		}
80570a708f8fSGustavo F. Padovan 	}
805823691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
80590a708f8fSGustavo F. Padovan 
80600a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
80610a708f8fSGustavo F. Padovan }
80620a708f8fSGustavo F. Padovan 
8063e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
8064e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
8065e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
8066e760ec12SJohan Hedberg  */
8067e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
8068327a7191SJohan Hedberg 						  struct hci_conn *hcon)
8069e760ec12SJohan Hedberg {
8070327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
8071327a7191SJohan Hedberg 
8072e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
8073e760ec12SJohan Hedberg 
8074e760ec12SJohan Hedberg 	if (c)
8075e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
8076e760ec12SJohan Hedberg 	else
8077e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
8078e760ec12SJohan Hedberg 
8079e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
8080e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
8081e760ec12SJohan Hedberg 			continue;
8082e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
8083e760ec12SJohan Hedberg 			continue;
8084327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
8085e760ec12SJohan Hedberg 			continue;
8086327a7191SJohan Hedberg 		if (src_type != c->src_type)
808754a1b626SJohan Hedberg 			continue;
8088e760ec12SJohan Hedberg 
8089e760ec12SJohan Hedberg 		l2cap_chan_hold(c);
8090e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
8091e760ec12SJohan Hedberg 		return c;
8092e760ec12SJohan Hedberg 	}
8093e760ec12SJohan Hedberg 
8094e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
8095e760ec12SJohan Hedberg 
8096e760ec12SJohan Hedberg 	return NULL;
8097e760ec12SJohan Hedberg }
8098e760ec12SJohan Hedberg 
8099539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
81000a708f8fSGustavo F. Padovan {
8101e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
81020a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
8103e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
8104e760ec12SJohan Hedberg 	u8 dst_type;
81050a708f8fSGustavo F. Padovan 
8106539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
8107539c496dSJohan Hedberg 		return;
8108539c496dSJohan Hedberg 
81096ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
81100a708f8fSGustavo F. Padovan 
8111dc0f5088SJohan Hedberg 	if (status) {
8112e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
8113dc0f5088SJohan Hedberg 		return;
8114ba6fc317SAndrei Emeltchenko 	}
8115dc0f5088SJohan Hedberg 
8116dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
8117dc0f5088SJohan Hedberg 	if (!conn)
8118dc0f5088SJohan Hedberg 		return;
8119dc0f5088SJohan Hedberg 
8120a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
8121e760ec12SJohan Hedberg 
8122e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
8123e760ec12SJohan Hedberg 	if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type))
8124e760ec12SJohan Hedberg 		return;
8125e760ec12SJohan Hedberg 
8126e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
8127e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
8128e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
8129e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
8130e760ec12SJohan Hedberg 	 */
8131327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
8132e760ec12SJohan Hedberg 	while (pchan) {
8133e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
8134e760ec12SJohan Hedberg 
8135e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
8136e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
8137e760ec12SJohan Hedberg 			goto next;
8138e760ec12SJohan Hedberg 
8139e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
8140e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
8141e760ec12SJohan Hedberg 		if (chan) {
8142e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
8143e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
8144a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
8145e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
8146e760ec12SJohan Hedberg 
8147e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
8148e760ec12SJohan Hedberg 		}
8149e760ec12SJohan Hedberg 
8150e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
8151e760ec12SJohan Hedberg next:
8152327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
8153e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
8154e760ec12SJohan Hedberg 		pchan = next;
8155e760ec12SJohan Hedberg 	}
8156e760ec12SJohan Hedberg 
8157dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
81580a708f8fSGustavo F. Padovan }
81590a708f8fSGustavo F. Padovan 
8160686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
81610a708f8fSGustavo F. Padovan {
81620a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
81630a708f8fSGustavo F. Padovan 
81640a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
81650a708f8fSGustavo F. Padovan 
8166686ebf28SUlisses Furquim 	if (!conn)
81679f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
81680a708f8fSGustavo F. Padovan 	return conn->disc_reason;
81690a708f8fSGustavo F. Padovan }
81700a708f8fSGustavo F. Padovan 
81713a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
81720a708f8fSGustavo F. Padovan {
81733a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
81743a6d576bSJohan Hedberg 		return;
81753a6d576bSJohan Hedberg 
81760a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
81770a708f8fSGustavo F. Padovan 
8178e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
81790a708f8fSGustavo F. Padovan }
81800a708f8fSGustavo F. Padovan 
81814343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
81820a708f8fSGustavo F. Padovan {
8183715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
81840a708f8fSGustavo F. Padovan 		return;
81850a708f8fSGustavo F. Padovan 
81860a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
81874343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
8188ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
81897d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
81907d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
81910f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
81920a708f8fSGustavo F. Padovan 	} else {
81934343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
8194c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
81950a708f8fSGustavo F. Padovan 	}
81960a708f8fSGustavo F. Padovan }
81970a708f8fSGustavo F. Padovan 
8198354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
81990a708f8fSGustavo F. Padovan {
82000a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
820148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
82020a708f8fSGustavo F. Padovan 
82030a708f8fSGustavo F. Padovan 	if (!conn)
8204354fe804SJohan Hedberg 		return;
82050a708f8fSGustavo F. Padovan 
820689d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
82070a708f8fSGustavo F. Padovan 
82083df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
82090a708f8fSGustavo F. Padovan 
82103df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
82116be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
82120a708f8fSGustavo F. Padovan 
821389d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
821489d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
8215f1cb9af5SVinicius Costa Gomes 
82162338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
821778eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
821878eb2f98SAndrei Emeltchenko 			continue;
821978eb2f98SAndrei Emeltchenko 		}
822078eb2f98SAndrei Emeltchenko 
8221191eb398SJohan Hedberg 		if (!status && encrypt)
8222f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
8223f1cb9af5SVinicius Costa Gomes 
822496eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
82256be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
82260a708f8fSGustavo F. Padovan 			continue;
82270a708f8fSGustavo F. Padovan 		}
82280a708f8fSGustavo F. Padovan 
822989bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
823089bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
8231d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
82324343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
82336be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
82340a708f8fSGustavo F. Padovan 			continue;
82350a708f8fSGustavo F. Padovan 		}
82360a708f8fSGustavo F. Padovan 
823789bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
8238693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
823993c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
82406d3c15daSJohan Hedberg 			else
8241ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8242fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
824315f02b91SLuiz Augusto von Dentz 			   !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
824415f02b91SLuiz Augusto von Dentz 			     chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
82450a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
8246df3c3931SJohan Hedberg 			__u16 res, stat;
82470a708f8fSGustavo F. Padovan 
8248693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
8249bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
8250df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
8251df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
82522dc4e510SGustavo Padovan 					chan->ops->defer(chan);
8253df3c3931SJohan Hedberg 				} else {
8254acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
8255df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
8256df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
8257df3c3931SJohan Hedberg 				}
82580a708f8fSGustavo F. Padovan 			} else {
8259acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
8260ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8261df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
8262df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
82630a708f8fSGustavo F. Padovan 			}
82640a708f8fSGustavo F. Padovan 
8265fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
8266fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
8267df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
8268df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
8269fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
8270fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
82712d369359SMat Martineau 
82722d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
82732d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
82742d369359SMat Martineau 				char buf[128];
82752d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
82762d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
82772d369359SMat Martineau 					       L2CAP_CONF_REQ,
8278e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
82792d369359SMat Martineau 					       buf);
82802d369359SMat Martineau 				chan->num_conf_req++;
82812d369359SMat Martineau 			}
82820a708f8fSGustavo F. Padovan 		}
82830a708f8fSGustavo F. Padovan 
82846be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
82850a708f8fSGustavo F. Padovan 	}
82860a708f8fSGustavo F. Padovan 
82873df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
82880a708f8fSGustavo F. Padovan }
82890a708f8fSGustavo F. Padovan 
82904d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
82914d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
82924d7ea8eeSLuiz Augusto von Dentz 			   u16 len)
82934d7ea8eeSLuiz Augusto von Dentz {
82944d7ea8eeSLuiz Augusto von Dentz 	if (!conn->rx_skb) {
82954d7ea8eeSLuiz Augusto von Dentz 		/* Allocate skb for the complete frame (with header) */
82964d7ea8eeSLuiz Augusto von Dentz 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
82974d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb)
82984d7ea8eeSLuiz Augusto von Dentz 			return -ENOMEM;
82994d7ea8eeSLuiz Augusto von Dentz 		/* Init rx_len */
83004d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len;
83014d7ea8eeSLuiz Augusto von Dentz 	}
83024d7ea8eeSLuiz Augusto von Dentz 
83034d7ea8eeSLuiz Augusto von Dentz 	/* Copy as much as the rx_skb can hold */
83044d7ea8eeSLuiz Augusto von Dentz 	len = min_t(u16, len, skb->len);
83054d7ea8eeSLuiz Augusto von Dentz 	skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
83064d7ea8eeSLuiz Augusto von Dentz 	skb_pull(skb, len);
83074d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len -= len;
83084d7ea8eeSLuiz Augusto von Dentz 
83094d7ea8eeSLuiz Augusto von Dentz 	return len;
83104d7ea8eeSLuiz Augusto von Dentz }
83114d7ea8eeSLuiz Augusto von Dentz 
83124d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
83134d7ea8eeSLuiz Augusto von Dentz {
83144d7ea8eeSLuiz Augusto von Dentz 	struct sk_buff *rx_skb;
83154d7ea8eeSLuiz Augusto von Dentz 	int len;
83164d7ea8eeSLuiz Augusto von Dentz 
83174d7ea8eeSLuiz Augusto von Dentz 	/* Append just enough to complete the header */
83184d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
83194d7ea8eeSLuiz Augusto von Dentz 
83204d7ea8eeSLuiz Augusto von Dentz 	/* If header could not be read just continue */
83214d7ea8eeSLuiz Augusto von Dentz 	if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
83224d7ea8eeSLuiz Augusto von Dentz 		return len;
83234d7ea8eeSLuiz Augusto von Dentz 
83244d7ea8eeSLuiz Augusto von Dentz 	rx_skb = conn->rx_skb;
83254d7ea8eeSLuiz Augusto von Dentz 	len = get_unaligned_le16(rx_skb->data);
83264d7ea8eeSLuiz Augusto von Dentz 
83274d7ea8eeSLuiz Augusto von Dentz 	/* Check if rx_skb has enough space to received all fragments */
83284d7ea8eeSLuiz Augusto von Dentz 	if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
83294d7ea8eeSLuiz Augusto von Dentz 		/* Update expected len */
83304d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
83314d7ea8eeSLuiz Augusto von Dentz 		return L2CAP_LEN_SIZE;
83324d7ea8eeSLuiz Augusto von Dentz 	}
83334d7ea8eeSLuiz Augusto von Dentz 
83344d7ea8eeSLuiz Augusto von Dentz 	/* Reset conn->rx_skb since it will need to be reallocated in order to
83354d7ea8eeSLuiz Augusto von Dentz 	 * fit all fragments.
83364d7ea8eeSLuiz Augusto von Dentz 	 */
83374d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
83384d7ea8eeSLuiz Augusto von Dentz 
83394d7ea8eeSLuiz Augusto von Dentz 	/* Reallocates rx_skb using the exact expected length */
83404d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, rx_skb,
83414d7ea8eeSLuiz Augusto von Dentz 			      len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
83424d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(rx_skb);
83434d7ea8eeSLuiz Augusto von Dentz 
83444d7ea8eeSLuiz Augusto von Dentz 	return len;
83454d7ea8eeSLuiz Augusto von Dentz }
83464d7ea8eeSLuiz Augusto von Dentz 
83474d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
83484d7ea8eeSLuiz Augusto von Dentz {
83494d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(conn->rx_skb);
83504d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
83514d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len = 0;
83524d7ea8eeSLuiz Augusto von Dentz }
83534d7ea8eeSLuiz Augusto von Dentz 
83549b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
83550a708f8fSGustavo F. Padovan {
83560a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
8357d73a0988SAndrei Emeltchenko 	int len;
83580a708f8fSGustavo F. Padovan 
83591d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
8360ca8bee5dSMarcel Holtmann 	if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
83611d13a254SAndrei Emeltchenko 		goto drop;
83620a708f8fSGustavo F. Padovan 
83630a708f8fSGustavo F. Padovan 	if (!conn)
8364baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
83650a708f8fSGustavo F. Padovan 
83660a708f8fSGustavo F. Padovan 	if (!conn)
83670a708f8fSGustavo F. Padovan 		goto drop;
83680a708f8fSGustavo F. Padovan 
83690a708f8fSGustavo F. Padovan 	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
83700a708f8fSGustavo F. Padovan 
8371d73a0988SAndrei Emeltchenko 	switch (flags) {
8372d73a0988SAndrei Emeltchenko 	case ACL_START:
8373d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
8374d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
83754d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb) {
83760a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
83774d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
83780a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
83790a708f8fSGustavo F. Padovan 		}
83800a708f8fSGustavo F. Padovan 
83814d7ea8eeSLuiz Augusto von Dentz 		/* Start fragment may not contain the L2CAP length so just
83824d7ea8eeSLuiz Augusto von Dentz 		 * copy the initial byte when that happens and use conn->mtu as
83834d7ea8eeSLuiz Augusto von Dentz 		 * expected length.
83844d7ea8eeSLuiz Augusto von Dentz 		 */
83854d7ea8eeSLuiz Augusto von Dentz 		if (skb->len < L2CAP_LEN_SIZE) {
83864d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_frag(conn, skb, conn->mtu) < 0)
83870a708f8fSGustavo F. Padovan 				goto drop;
83884d7ea8eeSLuiz Augusto von Dentz 			return;
83890a708f8fSGustavo F. Padovan 		}
83900a708f8fSGustavo F. Padovan 
83914d7ea8eeSLuiz Augusto von Dentz 		len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
83920a708f8fSGustavo F. Padovan 
83930a708f8fSGustavo F. Padovan 		if (len == skb->len) {
83940a708f8fSGustavo F. Padovan 			/* Complete frame received */
83950a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
83969b4c3336SArron Wang 			return;
83970a708f8fSGustavo F. Padovan 		}
83980a708f8fSGustavo F. Padovan 
83990a708f8fSGustavo F. Padovan 		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
84000a708f8fSGustavo F. Padovan 
84010a708f8fSGustavo F. Padovan 		if (skb->len > len) {
84020a708f8fSGustavo F. Padovan 			BT_ERR("Frame is too long (len %d, expected len %d)",
84030a708f8fSGustavo F. Padovan 			       skb->len, len);
84040a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
84050a708f8fSGustavo F. Padovan 			goto drop;
84060a708f8fSGustavo F. Padovan 		}
84070a708f8fSGustavo F. Padovan 
84084d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
84094d7ea8eeSLuiz Augusto von Dentz 		if (l2cap_recv_frag(conn, skb, len) < 0)
84100a708f8fSGustavo F. Padovan 			goto drop;
84110a708f8fSGustavo F. Padovan 
8412d73a0988SAndrei Emeltchenko 		break;
8413d73a0988SAndrei Emeltchenko 
8414d73a0988SAndrei Emeltchenko 	case ACL_CONT:
84150a708f8fSGustavo F. Padovan 		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
84160a708f8fSGustavo F. Padovan 
84174d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb) {
84180a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
84190a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
84200a708f8fSGustavo F. Padovan 			goto drop;
84210a708f8fSGustavo F. Padovan 		}
84220a708f8fSGustavo F. Padovan 
84234d7ea8eeSLuiz Augusto von Dentz 		/* Complete the L2CAP length if it has not been read */
84244d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
84254d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_len(conn, skb) < 0) {
84260a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
84270a708f8fSGustavo F. Padovan 				goto drop;
84280a708f8fSGustavo F. Padovan 			}
84290a708f8fSGustavo F. Padovan 
84304d7ea8eeSLuiz Augusto von Dentz 			/* Header still could not be read just continue */
84314d7ea8eeSLuiz Augusto von Dentz 			if (conn->rx_skb->len < L2CAP_LEN_SIZE)
84324d7ea8eeSLuiz Augusto von Dentz 				return;
84334d7ea8eeSLuiz Augusto von Dentz 		}
84344d7ea8eeSLuiz Augusto von Dentz 
84354d7ea8eeSLuiz Augusto von Dentz 		if (skb->len > conn->rx_len) {
84364d7ea8eeSLuiz Augusto von Dentz 			BT_ERR("Fragment is too long (len %d, expected %d)",
84374d7ea8eeSLuiz Augusto von Dentz 			       skb->len, conn->rx_len);
84384d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
84394d7ea8eeSLuiz Augusto von Dentz 			l2cap_conn_unreliable(conn, ECOMM);
84404d7ea8eeSLuiz Augusto von Dentz 			goto drop;
84414d7ea8eeSLuiz Augusto von Dentz 		}
84424d7ea8eeSLuiz Augusto von Dentz 
84434d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
84444d7ea8eeSLuiz Augusto von Dentz 		l2cap_recv_frag(conn, skb, skb->len);
84450a708f8fSGustavo F. Padovan 
84460a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
8447c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
8448c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
8449c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
8450c4e5bafaSJohan Hedberg 			 */
8451c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
84520a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
8453c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
84540a708f8fSGustavo F. Padovan 		}
8455d73a0988SAndrei Emeltchenko 		break;
84560a708f8fSGustavo F. Padovan 	}
84570a708f8fSGustavo F. Padovan 
84580a708f8fSGustavo F. Padovan drop:
84590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
84600a708f8fSGustavo F. Padovan }
84610a708f8fSGustavo F. Padovan 
8462354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
8463354fe804SJohan Hedberg 	.name		= "L2CAP",
8464539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
84653a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
8466354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
8467354fe804SJohan Hedberg };
8468354fe804SJohan Hedberg 
84690a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
84700a708f8fSGustavo F. Padovan {
847123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
84720a708f8fSGustavo F. Padovan 
8473333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
84740a708f8fSGustavo F. Padovan 
847523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
8476eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
8477eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
847889bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
847923691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
848023691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
84810a708f8fSGustavo F. Padovan 	}
84820a708f8fSGustavo F. Padovan 
8483333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
84840a708f8fSGustavo F. Padovan 
84850a708f8fSGustavo F. Padovan 	return 0;
84860a708f8fSGustavo F. Padovan }
84870a708f8fSGustavo F. Padovan 
84888e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
84890a708f8fSGustavo F. Padovan 
84900a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
84910a708f8fSGustavo F. Padovan 
849264274518SGustavo F. Padovan int __init l2cap_init(void)
84930a708f8fSGustavo F. Padovan {
84940a708f8fSGustavo F. Padovan 	int err;
84950a708f8fSGustavo F. Padovan 
8496bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
84970a708f8fSGustavo F. Padovan 	if (err < 0)
84980a708f8fSGustavo F. Padovan 		return err;
84990a708f8fSGustavo F. Padovan 
8500354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
8501354fe804SJohan Hedberg 
85021120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
85031120e4bfSMarcel Holtmann 		return 0;
85041120e4bfSMarcel Holtmann 
85052d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
85062d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
85070a708f8fSGustavo F. Padovan 
85080a708f8fSGustavo F. Padovan 	return 0;
85090a708f8fSGustavo F. Padovan }
85100a708f8fSGustavo F. Padovan 
851164274518SGustavo F. Padovan void l2cap_exit(void)
85120a708f8fSGustavo F. Padovan {
85130a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
8514354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
8515bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
85160a708f8fSGustavo F. Padovan }
85170a708f8fSGustavo F. Padovan 
85180a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
85190a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
85204be5ca67SLuiz Augusto von Dentz 
85214be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
85224be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
8523