xref: /openbmc/linux/net/bluetooth/l2cap_core.c (revision 9aa9d947)
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;
48462fcd53SLuiz Augusto von Dentz bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_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);
642d2cb306STetsuo Handa static void l2cap_retrans_timeout(struct work_struct *work);
652d2cb306STetsuo Handa static void l2cap_monitor_timeout(struct work_struct *work);
662d2cb306STetsuo Handa static void l2cap_ack_timeout(struct work_struct *work);
67608bcc6dSMat Martineau 
68a250e048SJohan Hedberg static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type)
694f1654e0SMarcel Holtmann {
70a250e048SJohan Hedberg 	if (link_type == LE_LINK) {
71a250e048SJohan Hedberg 		if (bdaddr_type == ADDR_LE_DEV_PUBLIC)
724f1654e0SMarcel Holtmann 			return BDADDR_LE_PUBLIC;
734f1654e0SMarcel Holtmann 		else
744f1654e0SMarcel Holtmann 			return BDADDR_LE_RANDOM;
754f1654e0SMarcel Holtmann 	}
764f1654e0SMarcel Holtmann 
774f1654e0SMarcel Holtmann 	return BDADDR_BREDR;
784f1654e0SMarcel Holtmann }
794f1654e0SMarcel Holtmann 
80a250e048SJohan Hedberg static inline u8 bdaddr_src_type(struct hci_conn *hcon)
81a250e048SJohan Hedberg {
82a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->src_type);
83a250e048SJohan Hedberg }
84a250e048SJohan Hedberg 
85a250e048SJohan Hedberg static inline u8 bdaddr_dst_type(struct hci_conn *hcon)
86a250e048SJohan Hedberg {
87a250e048SJohan Hedberg 	return bdaddr_type(hcon->type, hcon->dst_type);
88a250e048SJohan Hedberg }
89a250e048SJohan Hedberg 
900a708f8fSGustavo F. Padovan /* ---- L2CAP channels ---- */
9171ba0e56SGustavo F. Padovan 
922d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
932d792818SGustavo Padovan 						   u16 cid)
940a708f8fSGustavo F. Padovan {
953df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
96baa7e1faSGustavo F. Padovan 
973df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
983df91ea2SAndrei Emeltchenko 		if (c->dcid == cid)
993df91ea2SAndrei Emeltchenko 			return c;
1000a708f8fSGustavo F. Padovan 	}
1013df91ea2SAndrei Emeltchenko 	return NULL;
102baa7e1faSGustavo F. Padovan }
1030a708f8fSGustavo F. Padovan 
1042d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1052d792818SGustavo Padovan 						   u16 cid)
1060a708f8fSGustavo F. Padovan {
1073df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
108baa7e1faSGustavo F. Padovan 
1093df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1103df91ea2SAndrei Emeltchenko 		if (c->scid == cid)
1113df91ea2SAndrei Emeltchenko 			return c;
1120a708f8fSGustavo F. Padovan 	}
1133df91ea2SAndrei Emeltchenko 	return NULL;
114baa7e1faSGustavo F. Padovan }
1150a708f8fSGustavo F. Padovan 
1160a708f8fSGustavo F. Padovan /* Find channel with given SCID.
117d0be8347SLuiz Augusto von Dentz  * Returns a reference locked channel.
118d0be8347SLuiz Augusto von Dentz  */
1192d792818SGustavo Padovan static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn,
1202d792818SGustavo Padovan 						 u16 cid)
1210a708f8fSGustavo F. Padovan {
12248454079SGustavo F. Padovan 	struct l2cap_chan *c;
123baa7e1faSGustavo F. Padovan 
1243df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
125baa7e1faSGustavo F. Padovan 	c = __l2cap_get_chan_by_scid(conn, cid);
126d0be8347SLuiz Augusto von Dentz 	if (c) {
127d0be8347SLuiz Augusto von Dentz 		/* Only lock if chan reference is not 0 */
128d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
129ef191adeSMat Martineau 		if (c)
130ef191adeSMat Martineau 			l2cap_chan_lock(c);
131d0be8347SLuiz Augusto von Dentz 	}
1323df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
1333df91ea2SAndrei Emeltchenko 
13448454079SGustavo F. Padovan 	return c;
1350a708f8fSGustavo F. Padovan }
1360a708f8fSGustavo F. Padovan 
137b1a130b7SMat Martineau /* Find channel with given DCID.
138d0be8347SLuiz Augusto von Dentz  * Returns a reference locked channel.
139b1a130b7SMat Martineau  */
140b1a130b7SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn,
141b1a130b7SMat Martineau 						 u16 cid)
142b1a130b7SMat Martineau {
143b1a130b7SMat Martineau 	struct l2cap_chan *c;
144b1a130b7SMat Martineau 
145b1a130b7SMat Martineau 	mutex_lock(&conn->chan_lock);
146b1a130b7SMat Martineau 	c = __l2cap_get_chan_by_dcid(conn, cid);
147d0be8347SLuiz Augusto von Dentz 	if (c) {
148d0be8347SLuiz Augusto von Dentz 		/* Only lock if chan reference is not 0 */
149d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
150b1a130b7SMat Martineau 		if (c)
151b1a130b7SMat Martineau 			l2cap_chan_lock(c);
152d0be8347SLuiz Augusto von Dentz 	}
153b1a130b7SMat Martineau 	mutex_unlock(&conn->chan_lock);
154b1a130b7SMat Martineau 
155b1a130b7SMat Martineau 	return c;
156b1a130b7SMat Martineau }
157b1a130b7SMat Martineau 
1582d792818SGustavo Padovan static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1592d792818SGustavo Padovan 						    u8 ident)
1600a708f8fSGustavo F. Padovan {
1613df91ea2SAndrei Emeltchenko 	struct l2cap_chan *c;
162baa7e1faSGustavo F. Padovan 
1633df91ea2SAndrei Emeltchenko 	list_for_each_entry(c, &conn->chan_l, list) {
1643df91ea2SAndrei Emeltchenko 		if (c->ident == ident)
1653df91ea2SAndrei Emeltchenko 			return c;
1660a708f8fSGustavo F. Padovan 	}
1673df91ea2SAndrei Emeltchenko 	return NULL;
168baa7e1faSGustavo F. Padovan }
1690a708f8fSGustavo F. Padovan 
1705b155ef9SMat Martineau static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
1715b155ef9SMat Martineau 						  u8 ident)
1725b155ef9SMat Martineau {
1735b155ef9SMat Martineau 	struct l2cap_chan *c;
1745b155ef9SMat Martineau 
1755b155ef9SMat Martineau 	mutex_lock(&conn->chan_lock);
1765b155ef9SMat Martineau 	c = __l2cap_get_chan_by_ident(conn, ident);
177d0be8347SLuiz Augusto von Dentz 	if (c) {
178d0be8347SLuiz Augusto von Dentz 		/* Only lock if chan reference is not 0 */
179d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
1805b155ef9SMat Martineau 		if (c)
1815b155ef9SMat Martineau 			l2cap_chan_lock(c);
182d0be8347SLuiz Augusto von Dentz 	}
1835b155ef9SMat Martineau 	mutex_unlock(&conn->chan_lock);
1845b155ef9SMat Martineau 
1855b155ef9SMat Martineau 	return c;
1865b155ef9SMat Martineau }
1875b155ef9SMat Martineau 
18800f62726SLuiz Augusto von Dentz static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
18900f62726SLuiz Augusto von Dentz 						      u8 src_type)
1909e4425ffSGustavo F. Padovan {
19123691d75SGustavo F. Padovan 	struct l2cap_chan *c;
1929e4425ffSGustavo F. Padovan 
19323691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
19400f62726SLuiz Augusto von Dentz 		if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
19500f62726SLuiz Augusto von Dentz 			continue;
19600f62726SLuiz Augusto von Dentz 
19700f62726SLuiz Augusto von Dentz 		if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
19800f62726SLuiz Augusto von Dentz 			continue;
19900f62726SLuiz Augusto von Dentz 
2007eafc59eSMarcel Holtmann 		if (c->sport == psm && !bacmp(&c->src, src))
20123691d75SGustavo F. Padovan 			return c;
2029e4425ffSGustavo F. Padovan 	}
203250938cbSSzymon Janc 	return NULL;
204250938cbSSzymon Janc }
2059e4425ffSGustavo F. Padovan 
2069e4425ffSGustavo F. Padovan int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
2079e4425ffSGustavo F. Padovan {
20873b2ec18SGustavo F. Padovan 	int err;
20973b2ec18SGustavo F. Padovan 
210333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2119e4425ffSGustavo F. Padovan 
21200f62726SLuiz Augusto von Dentz 	if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
21373b2ec18SGustavo F. Padovan 		err = -EADDRINUSE;
21473b2ec18SGustavo F. Padovan 		goto done;
2159e4425ffSGustavo F. Padovan 	}
2169e4425ffSGustavo F. Padovan 
21773b2ec18SGustavo F. Padovan 	if (psm) {
2189e4425ffSGustavo F. Padovan 		chan->psm = psm;
2199e4425ffSGustavo F. Padovan 		chan->sport = psm;
22073b2ec18SGustavo F. Padovan 		err = 0;
22173b2ec18SGustavo F. Padovan 	} else {
22292594a51SJohan Hedberg 		u16 p, start, end, incr;
22392594a51SJohan Hedberg 
22492594a51SJohan Hedberg 		if (chan->src_type == BDADDR_BREDR) {
22592594a51SJohan Hedberg 			start = L2CAP_PSM_DYN_START;
22692594a51SJohan Hedberg 			end = L2CAP_PSM_AUTO_END;
22792594a51SJohan Hedberg 			incr = 2;
22892594a51SJohan Hedberg 		} else {
22992594a51SJohan Hedberg 			start = L2CAP_PSM_LE_DYN_START;
23092594a51SJohan Hedberg 			end = L2CAP_PSM_LE_DYN_END;
23192594a51SJohan Hedberg 			incr = 1;
23292594a51SJohan Hedberg 		}
2339e4425ffSGustavo F. Padovan 
23473b2ec18SGustavo F. Padovan 		err = -EINVAL;
23592594a51SJohan Hedberg 		for (p = start; p <= end; p += incr)
23600f62726SLuiz Augusto von Dentz 			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
23700f62726SLuiz Augusto von Dentz 							 chan->src_type)) {
23873b2ec18SGustavo F. Padovan 				chan->psm   = cpu_to_le16(p);
23973b2ec18SGustavo F. Padovan 				chan->sport = cpu_to_le16(p);
24073b2ec18SGustavo F. Padovan 				err = 0;
24173b2ec18SGustavo F. Padovan 				break;
24273b2ec18SGustavo F. Padovan 			}
24373b2ec18SGustavo F. Padovan 	}
24473b2ec18SGustavo F. Padovan 
24573b2ec18SGustavo F. Padovan done:
246333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
24773b2ec18SGustavo F. Padovan 	return err;
2489e4425ffSGustavo F. Padovan }
2496b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_add_psm);
2509e4425ffSGustavo F. Padovan 
2519e4425ffSGustavo F. Padovan int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
2529e4425ffSGustavo F. Padovan {
253333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
2549e4425ffSGustavo F. Padovan 
25514824308SJohan Hedberg 	/* Override the defaults (which are for conn-oriented) */
25614824308SJohan Hedberg 	chan->omtu = L2CAP_DEFAULT_MTU;
25714824308SJohan Hedberg 	chan->chan_type = L2CAP_CHAN_FIXED;
25814824308SJohan Hedberg 
2599e4425ffSGustavo F. Padovan 	chan->scid = scid;
2609e4425ffSGustavo F. Padovan 
261333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
2629e4425ffSGustavo F. Padovan 
2639e4425ffSGustavo F. Padovan 	return 0;
2649e4425ffSGustavo F. Padovan }
2659e4425ffSGustavo F. Padovan 
266baa7e1faSGustavo F. Padovan static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
2670a708f8fSGustavo F. Padovan {
268e77af755SJohan Hedberg 	u16 cid, dyn_end;
2690a708f8fSGustavo F. Padovan 
270e77af755SJohan Hedberg 	if (conn->hcon->type == LE_LINK)
271e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_LE_DYN_END;
272e77af755SJohan Hedberg 	else
273e77af755SJohan Hedberg 		dyn_end = L2CAP_CID_DYN_END;
274e77af755SJohan Hedberg 
275ab0c127fSJohan Hedberg 	for (cid = L2CAP_CID_DYN_START; cid <= dyn_end; cid++) {
276baa7e1faSGustavo F. Padovan 		if (!__l2cap_get_chan_by_scid(conn, cid))
2770a708f8fSGustavo F. Padovan 			return cid;
2780a708f8fSGustavo F. Padovan 	}
2790a708f8fSGustavo F. Padovan 
2800a708f8fSGustavo F. Padovan 	return 0;
2810a708f8fSGustavo F. Padovan }
2820a708f8fSGustavo F. Padovan 
283f93fa273SGustavo Padovan static void l2cap_state_change(struct l2cap_chan *chan, int state)
28489bc500eSGustavo F. Padovan {
28542d2d87cSAndrei Emeltchenko 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
286badaaa00SGustavo F. Padovan 	       state_to_string(state));
287badaaa00SGustavo F. Padovan 
28889bc500eSGustavo F. Padovan 	chan->state = state;
28953f52121SGustavo Padovan 	chan->ops->state_change(chan, state, 0);
29089bc500eSGustavo F. Padovan }
29189bc500eSGustavo F. Padovan 
292f8e73017SGustavo Padovan static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
293f8e73017SGustavo Padovan 						int state, int err)
2942e0052e4SAndrei Emeltchenko {
295f8e73017SGustavo Padovan 	chan->state = state;
29653f52121SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
2972e0052e4SAndrei Emeltchenko }
2982e0052e4SAndrei Emeltchenko 
2992e0052e4SAndrei Emeltchenko static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
3002e0052e4SAndrei Emeltchenko {
301f8e73017SGustavo Padovan 	chan->ops->state_change(chan, chan->state, err);
3022e0052e4SAndrei Emeltchenko }
3032e0052e4SAndrei Emeltchenko 
3044239d16fSMat Martineau static void __set_retrans_timer(struct l2cap_chan *chan)
3054239d16fSMat Martineau {
3064239d16fSMat Martineau 	if (!delayed_work_pending(&chan->monitor_timer) &&
3074239d16fSMat Martineau 	    chan->retrans_timeout) {
3084239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->retrans_timer,
3094239d16fSMat Martineau 				msecs_to_jiffies(chan->retrans_timeout));
3104239d16fSMat Martineau 	}
3114239d16fSMat Martineau }
3124239d16fSMat Martineau 
3134239d16fSMat Martineau static void __set_monitor_timer(struct l2cap_chan *chan)
3144239d16fSMat Martineau {
3154239d16fSMat Martineau 	__clear_retrans_timer(chan);
3164239d16fSMat Martineau 	if (chan->monitor_timeout) {
3174239d16fSMat Martineau 		l2cap_set_timer(chan, &chan->monitor_timer,
3184239d16fSMat Martineau 				msecs_to_jiffies(chan->monitor_timeout));
3194239d16fSMat Martineau 	}
3204239d16fSMat Martineau }
3214239d16fSMat Martineau 
322608bcc6dSMat Martineau static struct sk_buff *l2cap_ertm_seq_in_queue(struct sk_buff_head *head,
323608bcc6dSMat Martineau 					       u16 seq)
324608bcc6dSMat Martineau {
325608bcc6dSMat Martineau 	struct sk_buff *skb;
326608bcc6dSMat Martineau 
327608bcc6dSMat Martineau 	skb_queue_walk(head, skb) {
328a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.txseq == seq)
329608bcc6dSMat Martineau 			return skb;
330608bcc6dSMat Martineau 	}
331608bcc6dSMat Martineau 
332608bcc6dSMat Martineau 	return NULL;
333608bcc6dSMat Martineau }
334608bcc6dSMat Martineau 
3353c588192SMat Martineau /* ---- L2CAP sequence number lists ---- */
3363c588192SMat Martineau 
3373c588192SMat Martineau /* For ERTM, ordered lists of sequence numbers must be tracked for
3383c588192SMat Martineau  * SREJ requests that are received and for frames that are to be
3393c588192SMat Martineau  * retransmitted. These seq_list functions implement a singly-linked
3403c588192SMat Martineau  * list in an array, where membership in the list can also be checked
3413c588192SMat Martineau  * in constant time. Items can also be added to the tail of the list
3423c588192SMat Martineau  * and removed from the head in constant time, without further memory
3433c588192SMat Martineau  * allocs or frees.
3443c588192SMat Martineau  */
3453c588192SMat Martineau 
3463c588192SMat Martineau static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
3473c588192SMat Martineau {
3483c588192SMat Martineau 	size_t alloc_size, i;
3493c588192SMat Martineau 
3503c588192SMat Martineau 	/* Allocated size is a power of 2 to map sequence numbers
3513c588192SMat Martineau 	 * (which may be up to 14 bits) in to a smaller array that is
3523c588192SMat Martineau 	 * sized for the negotiated ERTM transmit windows.
3533c588192SMat Martineau 	 */
3543c588192SMat Martineau 	alloc_size = roundup_pow_of_two(size);
3553c588192SMat Martineau 
3566da2ec56SKees Cook 	seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
3573c588192SMat Martineau 	if (!seq_list->list)
3583c588192SMat Martineau 		return -ENOMEM;
3593c588192SMat Martineau 
3603c588192SMat Martineau 	seq_list->mask = alloc_size - 1;
3613c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3623c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3633c588192SMat Martineau 	for (i = 0; i < alloc_size; i++)
3643c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
3653c588192SMat Martineau 
3663c588192SMat Martineau 	return 0;
3673c588192SMat Martineau }
3683c588192SMat Martineau 
3693c588192SMat Martineau static inline void l2cap_seq_list_free(struct l2cap_seq_list *seq_list)
3703c588192SMat Martineau {
3713c588192SMat Martineau 	kfree(seq_list->list);
3723c588192SMat Martineau }
3733c588192SMat Martineau 
3743c588192SMat Martineau static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list,
3753c588192SMat Martineau 					   u16 seq)
3763c588192SMat Martineau {
3773c588192SMat Martineau 	/* Constant-time check for list membership */
3783c588192SMat Martineau 	return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR;
3793c588192SMat Martineau }
3803c588192SMat Martineau 
38103a0c5d6SJohan Hedberg static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list)
3823c588192SMat Martineau {
38303a0c5d6SJohan Hedberg 	u16 seq = seq_list->head;
3843c588192SMat Martineau 	u16 mask = seq_list->mask;
3853c588192SMat Martineau 
3863c588192SMat Martineau 	seq_list->head = seq_list->list[seq & mask];
3873c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR;
3883c588192SMat Martineau 
3893c588192SMat Martineau 	if (seq_list->head == L2CAP_SEQ_LIST_TAIL) {
3903c588192SMat Martineau 		seq_list->head = L2CAP_SEQ_LIST_CLEAR;
3913c588192SMat Martineau 		seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
3923c588192SMat Martineau 	}
3933c588192SMat Martineau 
3943c588192SMat Martineau 	return seq;
3953c588192SMat Martineau }
3963c588192SMat Martineau 
3973c588192SMat Martineau static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list)
3983c588192SMat Martineau {
3993c588192SMat Martineau 	u16 i;
400f522ae36SGustavo Padovan 
401f522ae36SGustavo Padovan 	if (seq_list->head == L2CAP_SEQ_LIST_CLEAR)
402f522ae36SGustavo Padovan 		return;
403f522ae36SGustavo Padovan 
4043c588192SMat Martineau 	for (i = 0; i <= seq_list->mask; i++)
4053c588192SMat Martineau 		seq_list->list[i] = L2CAP_SEQ_LIST_CLEAR;
4063c588192SMat Martineau 
4073c588192SMat Martineau 	seq_list->head = L2CAP_SEQ_LIST_CLEAR;
4083c588192SMat Martineau 	seq_list->tail = L2CAP_SEQ_LIST_CLEAR;
4093c588192SMat Martineau }
4103c588192SMat Martineau 
4113c588192SMat Martineau static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq)
4123c588192SMat Martineau {
4133c588192SMat Martineau 	u16 mask = seq_list->mask;
4143c588192SMat Martineau 
4153c588192SMat Martineau 	/* All appends happen in constant time */
4163c588192SMat Martineau 
417f522ae36SGustavo Padovan 	if (seq_list->list[seq & mask] != L2CAP_SEQ_LIST_CLEAR)
418f522ae36SGustavo Padovan 		return;
419f522ae36SGustavo Padovan 
4203c588192SMat Martineau 	if (seq_list->tail == L2CAP_SEQ_LIST_CLEAR)
4213c588192SMat Martineau 		seq_list->head = seq;
4223c588192SMat Martineau 	else
4233c588192SMat Martineau 		seq_list->list[seq_list->tail & mask] = seq;
4243c588192SMat Martineau 
4253c588192SMat Martineau 	seq_list->tail = seq;
4263c588192SMat Martineau 	seq_list->list[seq & mask] = L2CAP_SEQ_LIST_TAIL;
4273c588192SMat Martineau }
4283c588192SMat Martineau 
429721c4181SGustavo F. Padovan static void l2cap_chan_timeout(struct work_struct *work)
430ab07801dSGustavo F. Padovan {
431721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
432721c4181SGustavo F. Padovan 					       chan_timer.work);
4333df91ea2SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
434ab07801dSGustavo F. Padovan 	int reason;
435ab07801dSGustavo F. Padovan 
436e05dcc32SAndrei Emeltchenko 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
437ab07801dSGustavo F. Padovan 
4383df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
4396c08fc89SManish Mandlik 	/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
4406c08fc89SManish Mandlik 	 * this work. No need to call l2cap_chan_hold(chan) here again.
4416c08fc89SManish Mandlik 	 */
4426be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
443ab07801dSGustavo F. Padovan 
44489bc500eSGustavo F. Padovan 	if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
445ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
44689bc500eSGustavo F. Padovan 	else if (chan->state == BT_CONNECT &&
447ab07801dSGustavo F. Padovan 		 chan->sec_level != BT_SECURITY_SDP)
448ab07801dSGustavo F. Padovan 		reason = ECONNREFUSED;
449ab07801dSGustavo F. Padovan 	else
450ab07801dSGustavo F. Padovan 		reason = ETIMEDOUT;
451ab07801dSGustavo F. Padovan 
4520f852724SGustavo F. Padovan 	l2cap_chan_close(chan, reason);
453ab07801dSGustavo F. Padovan 
45480b98027SGustavo Padovan 	chan->ops->close(chan);
4553df91ea2SAndrei Emeltchenko 
4566c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
457371fd835SUlisses Furquim 	l2cap_chan_put(chan);
4586c08fc89SManish Mandlik 
4596c08fc89SManish Mandlik 	mutex_unlock(&conn->chan_lock);
460ab07801dSGustavo F. Padovan }
461ab07801dSGustavo F. Padovan 
462eef1d9b6SGustavo Padovan struct l2cap_chan *l2cap_chan_create(void)
4630a708f8fSGustavo F. Padovan {
46448454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4650a708f8fSGustavo F. Padovan 
46648454079SGustavo F. Padovan 	chan = kzalloc(sizeof(*chan), GFP_ATOMIC);
46748454079SGustavo F. Padovan 	if (!chan)
46848454079SGustavo F. Padovan 		return NULL;
4690a708f8fSGustavo F. Padovan 
470be859723STetsuo Handa 	skb_queue_head_init(&chan->tx_q);
471be859723STetsuo Handa 	skb_queue_head_init(&chan->srej_q);
472c03b355eSAndrei Emeltchenko 	mutex_init(&chan->lock);
473c03b355eSAndrei Emeltchenko 
474ff714119SJohan Hedberg 	/* Set default lock nesting level */
475ff714119SJohan Hedberg 	atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
476ff714119SJohan Hedberg 
477333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
47823691d75SGustavo F. Padovan 	list_add(&chan->global_l, &chan_list);
479333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
48023691d75SGustavo F. Padovan 
481721c4181SGustavo F. Padovan 	INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout);
4822d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout);
4832d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout);
4842d2cb306STetsuo Handa 	INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout);
485ab07801dSGustavo F. Padovan 
48689bc500eSGustavo F. Padovan 	chan->state = BT_OPEN;
48789bc500eSGustavo F. Padovan 
488144ad330SSyam Sidhardhan 	kref_init(&chan->kref);
48971ba0e56SGustavo F. Padovan 
4902827011fSMat Martineau 	/* This flag is cleared in l2cap_chan_ready() */
4912827011fSMat Martineau 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
4922827011fSMat Martineau 
493eef1d9b6SGustavo Padovan 	BT_DBG("chan %p", chan);
494abc545b8SSzymon Janc 
49548454079SGustavo F. Padovan 	return chan;
4960a708f8fSGustavo F. Padovan }
4976b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_create);
4980a708f8fSGustavo F. Padovan 
499144ad330SSyam Sidhardhan static void l2cap_chan_destroy(struct kref *kref)
5006ff5abbfSGustavo F. Padovan {
501144ad330SSyam Sidhardhan 	struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref);
502144ad330SSyam Sidhardhan 
5034af66c69SJaganath Kanakkassery 	BT_DBG("chan %p", chan);
5044af66c69SJaganath Kanakkassery 
505333055f2SGustavo F. Padovan 	write_lock(&chan_list_lock);
50623691d75SGustavo F. Padovan 	list_del(&chan->global_l);
507333055f2SGustavo F. Padovan 	write_unlock(&chan_list_lock);
50823691d75SGustavo F. Padovan 
5094af66c69SJaganath Kanakkassery 	kfree(chan);
5106ff5abbfSGustavo F. Padovan }
5116ff5abbfSGustavo F. Padovan 
51230648372SJaganath Kanakkassery void l2cap_chan_hold(struct l2cap_chan *c)
51330648372SJaganath Kanakkassery {
51493917fd2SKai Ye 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
51530648372SJaganath Kanakkassery 
516144ad330SSyam Sidhardhan 	kref_get(&c->kref);
51730648372SJaganath Kanakkassery }
51830648372SJaganath Kanakkassery 
519d0be8347SLuiz Augusto von Dentz struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
520d0be8347SLuiz Augusto von Dentz {
521d0be8347SLuiz Augusto von Dentz 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
522d0be8347SLuiz Augusto von Dentz 
523d0be8347SLuiz Augusto von Dentz 	if (!kref_get_unless_zero(&c->kref))
524d0be8347SLuiz Augusto von Dentz 		return NULL;
525d0be8347SLuiz Augusto von Dentz 
526d0be8347SLuiz Augusto von Dentz 	return c;
527d0be8347SLuiz Augusto von Dentz }
528d0be8347SLuiz Augusto von Dentz 
52930648372SJaganath Kanakkassery void l2cap_chan_put(struct l2cap_chan *c)
53030648372SJaganath Kanakkassery {
53193917fd2SKai Ye 	BT_DBG("chan %p orig refcnt %u", c, kref_read(&c->kref));
53230648372SJaganath Kanakkassery 
533144ad330SSyam Sidhardhan 	kref_put(&c->kref, l2cap_chan_destroy);
53430648372SJaganath Kanakkassery }
5356b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_put);
53630648372SJaganath Kanakkassery 
537bd4b1653SAndrei Emeltchenko void l2cap_chan_set_defaults(struct l2cap_chan *chan)
538bd4b1653SAndrei Emeltchenko {
539bd4b1653SAndrei Emeltchenko 	chan->fcs  = L2CAP_FCS_CRC16;
540bd4b1653SAndrei Emeltchenko 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
541bd4b1653SAndrei Emeltchenko 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
542bd4b1653SAndrei Emeltchenko 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
5436a5e8165SJukka Rissanen 	chan->remote_max_tx = chan->max_tx;
5446a5e8165SJukka Rissanen 	chan->remote_tx_win = chan->tx_win;
545c20f8e35SMat Martineau 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
546bd4b1653SAndrei Emeltchenko 	chan->sec_level = BT_SECURITY_LOW;
5476a5e8165SJukka Rissanen 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
5486a5e8165SJukka Rissanen 	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
5496a5e8165SJukka Rissanen 	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
5503a9d54b1SArchie Pusaka 
5516a5e8165SJukka Rissanen 	chan->conf_state = 0;
5523a9d54b1SArchie Pusaka 	set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
553bd4b1653SAndrei Emeltchenko 
554bd4b1653SAndrei Emeltchenko 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
555bd4b1653SAndrei Emeltchenko }
5566b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
557bd4b1653SAndrei Emeltchenko 
558ba8f5289SLuiz Augusto von Dentz static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
55938319713SJohan Hedberg {
5600ce43ce6SJohan Hedberg 	chan->sdu = NULL;
5610ce43ce6SJohan Hedberg 	chan->sdu_last_frag = NULL;
5620ce43ce6SJohan Hedberg 	chan->sdu_len = 0;
563ba8f5289SLuiz Augusto von Dentz 	chan->tx_credits = tx_credits;
564fe149310SLuiz Augusto von Dentz 	/* Derive MPS from connection MTU to stop HCI fragmentation */
565fe149310SLuiz Augusto von Dentz 	chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
56696cd8eaaSLuiz Augusto von Dentz 	/* Give enough credits for a full packet */
56796cd8eaaSLuiz Augusto von Dentz 	chan->rx_credits = (chan->imtu / chan->mps) + 1;
5680ce43ce6SJohan Hedberg 
5690ce43ce6SJohan Hedberg 	skb_queue_head_init(&chan->tx_q);
57038319713SJohan Hedberg }
57138319713SJohan Hedberg 
57215f02b91SLuiz Augusto von Dentz static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
57315f02b91SLuiz Augusto von Dentz {
57415f02b91SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, tx_credits);
57515f02b91SLuiz Augusto von Dentz 
57615f02b91SLuiz Augusto von Dentz 	/* L2CAP implementations shall support a minimum MPS of 64 octets */
57715f02b91SLuiz Augusto von Dentz 	if (chan->mps < L2CAP_ECRED_MIN_MPS) {
57815f02b91SLuiz Augusto von Dentz 		chan->mps = L2CAP_ECRED_MIN_MPS;
57915f02b91SLuiz Augusto von Dentz 		chan->rx_credits = (chan->imtu / chan->mps) + 1;
58015f02b91SLuiz Augusto von Dentz 	}
58115f02b91SLuiz Augusto von Dentz }
58215f02b91SLuiz Augusto von Dentz 
58393c3e8f5SAndrei Emeltchenko void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
5840a708f8fSGustavo F. Padovan {
5850a708f8fSGustavo F. Padovan 	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
586097db76cSAndrei Emeltchenko 	       __le16_to_cpu(chan->psm), chan->dcid);
5870a708f8fSGustavo F. Padovan 
5889f5a0d7bSAndrei Emeltchenko 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
5890a708f8fSGustavo F. Padovan 
5908c1d787bSGustavo F. Padovan 	chan->conn = conn;
5910a708f8fSGustavo F. Padovan 
5925491120eSAndrei Emeltchenko 	switch (chan->chan_type) {
5935491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_ORIENTED:
5940a708f8fSGustavo F. Padovan 		/* Alloc CID for connection-oriented socket */
595fe4128e0SGustavo F. Padovan 		chan->scid = l2cap_alloc_cid(conn);
59621626e62SJohan Hedberg 		if (conn->hcon->type == ACL_LINK)
5970c1bc5c6SGustavo F. Padovan 			chan->omtu = L2CAP_DEFAULT_MTU;
5985491120eSAndrei Emeltchenko 		break;
5995491120eSAndrei Emeltchenko 
6005491120eSAndrei Emeltchenko 	case L2CAP_CHAN_CONN_LESS:
6010a708f8fSGustavo F. Padovan 		/* Connectionless socket */
602fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_CONN_LESS;
603fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_CONN_LESS;
6040c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
6055491120eSAndrei Emeltchenko 		break;
6065491120eSAndrei Emeltchenko 
6072338a7e0SJohan Hedberg 	case L2CAP_CHAN_FIXED:
6082338a7e0SJohan Hedberg 		/* Caller will set CID and CID specific MTU values */
609416fa752SAndrei Emeltchenko 		break;
610416fa752SAndrei Emeltchenko 
6115491120eSAndrei Emeltchenko 	default:
6120a708f8fSGustavo F. Padovan 		/* Raw socket can send/recv signalling messages only */
613fe4128e0SGustavo F. Padovan 		chan->scid = L2CAP_CID_SIGNALING;
614fe4128e0SGustavo F. Padovan 		chan->dcid = L2CAP_CID_SIGNALING;
6150c1bc5c6SGustavo F. Padovan 		chan->omtu = L2CAP_DEFAULT_MTU;
6160a708f8fSGustavo F. Padovan 	}
6170a708f8fSGustavo F. Padovan 
6188f7975b1SAndrei Emeltchenko 	chan->local_id		= L2CAP_BESTEFFORT_ID;
6198f7975b1SAndrei Emeltchenko 	chan->local_stype	= L2CAP_SERV_BESTEFFORT;
6208f7975b1SAndrei Emeltchenko 	chan->local_msdu	= L2CAP_DEFAULT_MAX_SDU_SIZE;
6218f7975b1SAndrei Emeltchenko 	chan->local_sdu_itime	= L2CAP_DEFAULT_SDU_ITIME;
6228f7975b1SAndrei Emeltchenko 	chan->local_acc_lat	= L2CAP_DEFAULT_ACC_LAT;
6238936fa6dSAndrei Emeltchenko 	chan->local_flush_to	= L2CAP_EFS_DEFAULT_FLUSH_TO;
6248f7975b1SAndrei Emeltchenko 
625371fd835SUlisses Furquim 	l2cap_chan_hold(chan);
626baa7e1faSGustavo F. Padovan 
627c16900cfSJohan Hedberg 	/* Only keep a reference for fixed channels if they requested it */
628c16900cfSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_FIXED ||
629c16900cfSJohan Hedberg 	    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
6305ee9891dSJohan Hedberg 		hci_conn_hold(conn->hcon);
6315ee9891dSJohan Hedberg 
6323df91ea2SAndrei Emeltchenko 	list_add(&chan->list, &conn->chan_l);
633643162a8SAndrei Emeltchenko }
634643162a8SAndrei Emeltchenko 
635466f8004SAndrei Emeltchenko void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
636643162a8SAndrei Emeltchenko {
637643162a8SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
638643162a8SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
6393df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
6400a708f8fSGustavo F. Padovan }
6410a708f8fSGustavo F. Padovan 
642466f8004SAndrei Emeltchenko void l2cap_chan_del(struct l2cap_chan *chan, int err)
6430a708f8fSGustavo F. Padovan {
6448c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
6450a708f8fSGustavo F. Padovan 
646c9b66675SGustavo F. Padovan 	__clear_chan_timer(chan);
6470a708f8fSGustavo F. Padovan 
64849d11741SJohan Hedberg 	BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
64949d11741SJohan Hedberg 	       state_to_string(chan->state));
6500a708f8fSGustavo F. Padovan 
65172847ce0SJohan Hedberg 	chan->ops->teardown(chan, err);
65272847ce0SJohan Hedberg 
6530a708f8fSGustavo F. Padovan 	if (conn) {
65456f60984SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
655baa7e1faSGustavo F. Padovan 		/* Delete from channel list */
6563df91ea2SAndrei Emeltchenko 		list_del(&chan->list);
6573d57dc68SGustavo F. Padovan 
658371fd835SUlisses Furquim 		l2cap_chan_put(chan);
659baa7e1faSGustavo F. Padovan 
6608c1d787bSGustavo F. Padovan 		chan->conn = NULL;
6613cabbfdaSAndrei Emeltchenko 
662c16900cfSJohan Hedberg 		/* Reference was only held for non-fixed channels or
663c16900cfSJohan Hedberg 		 * fixed channels that explicitly requested it using the
664c16900cfSJohan Hedberg 		 * FLAG_HOLD_HCI_CONN flag.
665c16900cfSJohan Hedberg 		 */
666c16900cfSJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_FIXED ||
667c16900cfSJohan Hedberg 		    test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
66876a68ba0SDavid Herrmann 			hci_conn_drop(conn->hcon);
66956f60984SAndrei Emeltchenko 
67056f60984SAndrei Emeltchenko 		if (mgr && mgr->bredr_chan == chan)
67156f60984SAndrei Emeltchenko 			mgr->bredr_chan = NULL;
6720a708f8fSGustavo F. Padovan 	}
6730a708f8fSGustavo F. Padovan 
674419e08c1SAndrei Emeltchenko 	if (chan->hs_hchan) {
675419e08c1SAndrei Emeltchenko 		struct hci_chan *hs_hchan = chan->hs_hchan;
676419e08c1SAndrei Emeltchenko 
677419e08c1SAndrei Emeltchenko 		BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
678419e08c1SAndrei Emeltchenko 		amp_disconnect_logical_link(hs_hchan);
679419e08c1SAndrei Emeltchenko 	}
680419e08c1SAndrei Emeltchenko 
6812827011fSMat Martineau 	if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
6826ff5abbfSGustavo F. Padovan 		return;
6832ead70b8SGustavo F. Padovan 
684ee556f66SGustavo Padovan 	switch (chan->mode) {
685ee556f66SGustavo Padovan 	case L2CAP_MODE_BASIC:
686ee556f66SGustavo Padovan 		break;
6870a708f8fSGustavo F. Padovan 
68838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
68915f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
690177f8f2bSJohan Hedberg 		skb_queue_purge(&chan->tx_q);
69138319713SJohan Hedberg 		break;
69238319713SJohan Hedberg 
693ee556f66SGustavo Padovan 	case L2CAP_MODE_ERTM:
6941a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
6951a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
6961a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
6970a708f8fSGustavo F. Padovan 
698f1c6775bSGustavo F. Padovan 		skb_queue_purge(&chan->srej_q);
6990a708f8fSGustavo F. Padovan 
7003c588192SMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
7013c588192SMat Martineau 		l2cap_seq_list_free(&chan->retrans_list);
70219186c7bSGustavo A. R. Silva 		fallthrough;
703ee556f66SGustavo Padovan 
704ee556f66SGustavo Padovan 	case L2CAP_MODE_STREAMING:
705ee556f66SGustavo Padovan 		skb_queue_purge(&chan->tx_q);
706ee556f66SGustavo Padovan 		break;
7070a708f8fSGustavo F. Padovan 	}
7080a708f8fSGustavo F. Padovan }
7096b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_del);
7100a708f8fSGustavo F. Padovan 
711*9aa9d947SLuiz Augusto von Dentz static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
712*9aa9d947SLuiz Augusto von Dentz 				 l2cap_chan_func_t func, void *data)
713*9aa9d947SLuiz Augusto von Dentz {
714*9aa9d947SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *l;
715*9aa9d947SLuiz Augusto von Dentz 
716*9aa9d947SLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
717*9aa9d947SLuiz Augusto von Dentz 		if (chan->ident == id)
718*9aa9d947SLuiz Augusto von Dentz 			func(chan, data);
719*9aa9d947SLuiz Augusto von Dentz 	}
720*9aa9d947SLuiz Augusto von Dentz }
721*9aa9d947SLuiz Augusto von Dentz 
722da49b602SLuiz Augusto von Dentz static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
723da49b602SLuiz Augusto von Dentz 			      void *data)
724da49b602SLuiz Augusto von Dentz {
725da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
726da49b602SLuiz Augusto von Dentz 
727da49b602SLuiz Augusto von Dentz 	list_for_each_entry(chan, &conn->chan_l, list) {
728da49b602SLuiz Augusto von Dentz 		func(chan, data);
729da49b602SLuiz Augusto von Dentz 	}
730da49b602SLuiz Augusto von Dentz }
731da49b602SLuiz Augusto von Dentz 
732da49b602SLuiz Augusto von Dentz void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
733da49b602SLuiz Augusto von Dentz 		     void *data)
734da49b602SLuiz Augusto von Dentz {
735da49b602SLuiz Augusto von Dentz 	if (!conn)
736da49b602SLuiz Augusto von Dentz 		return;
737da49b602SLuiz Augusto von Dentz 
738da49b602SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
739da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, func, data);
740da49b602SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
741da49b602SLuiz Augusto von Dentz }
742da49b602SLuiz Augusto von Dentz 
743da49b602SLuiz Augusto von Dentz EXPORT_SYMBOL_GPL(l2cap_chan_list);
744da49b602SLuiz Augusto von Dentz 
745f3d82d0cSJohan Hedberg static void l2cap_conn_update_id_addr(struct work_struct *work)
746387a33e3SJohan Hedberg {
747f3d82d0cSJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
748f3d82d0cSJohan Hedberg 					       id_addr_update_work);
749f3d82d0cSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
750387a33e3SJohan Hedberg 	struct l2cap_chan *chan;
751387a33e3SJohan Hedberg 
752387a33e3SJohan Hedberg 	mutex_lock(&conn->chan_lock);
753387a33e3SJohan Hedberg 
754387a33e3SJohan Hedberg 	list_for_each_entry(chan, &conn->chan_l, list) {
755387a33e3SJohan Hedberg 		l2cap_chan_lock(chan);
756387a33e3SJohan Hedberg 		bacpy(&chan->dst, &hcon->dst);
757a250e048SJohan Hedberg 		chan->dst_type = bdaddr_dst_type(hcon);
758387a33e3SJohan Hedberg 		l2cap_chan_unlock(chan);
759387a33e3SJohan Hedberg 	}
760387a33e3SJohan Hedberg 
761387a33e3SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
762387a33e3SJohan Hedberg }
763387a33e3SJohan Hedberg 
76427e2d4c8SJohan Hedberg static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
76527e2d4c8SJohan Hedberg {
76627e2d4c8SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
76727e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
76827e2d4c8SJohan Hedberg 	u16 result;
76927e2d4c8SJohan Hedberg 
77027e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
771571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHORIZATION;
77227e2d4c8SJohan Hedberg 	else
773571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
77427e2d4c8SJohan Hedberg 
77527e2d4c8SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
77627e2d4c8SJohan Hedberg 
77727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(chan->scid);
77827e2d4c8SJohan Hedberg 	rsp.mtu     = cpu_to_le16(chan->imtu);
7793916aed8SJohan Hedberg 	rsp.mps     = cpu_to_le16(chan->mps);
7800cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(chan->rx_credits);
78127e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
78227e2d4c8SJohan Hedberg 
78327e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
78427e2d4c8SJohan Hedberg 		       &rsp);
78527e2d4c8SJohan Hedberg }
78627e2d4c8SJohan Hedberg 
78715f02b91SLuiz Augusto von Dentz static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
78815f02b91SLuiz Augusto von Dentz {
78915f02b91SLuiz Augusto von Dentz 	l2cap_state_change(chan, BT_DISCONN);
79015f02b91SLuiz Augusto von Dentz 
791*9aa9d947SLuiz Augusto von Dentz 	__l2cap_ecred_conn_rsp_defer(chan);
79215f02b91SLuiz Augusto von Dentz }
79315f02b91SLuiz Augusto von Dentz 
794791d60f7SJohan Hedberg static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
795791d60f7SJohan Hedberg {
796791d60f7SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
797791d60f7SJohan Hedberg 	struct l2cap_conn_rsp rsp;
798791d60f7SJohan Hedberg 	u16 result;
799791d60f7SJohan Hedberg 
800791d60f7SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
801791d60f7SJohan Hedberg 		result = L2CAP_CR_SEC_BLOCK;
802791d60f7SJohan Hedberg 	else
803791d60f7SJohan Hedberg 		result = L2CAP_CR_BAD_PSM;
804791d60f7SJohan Hedberg 
805791d60f7SJohan Hedberg 	l2cap_state_change(chan, BT_DISCONN);
806791d60f7SJohan Hedberg 
807791d60f7SJohan Hedberg 	rsp.scid   = cpu_to_le16(chan->dcid);
808791d60f7SJohan Hedberg 	rsp.dcid   = cpu_to_le16(chan->scid);
809791d60f7SJohan Hedberg 	rsp.result = cpu_to_le16(result);
810dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
811791d60f7SJohan Hedberg 
812791d60f7SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
813791d60f7SJohan Hedberg }
814791d60f7SJohan Hedberg 
8150f852724SGustavo F. Padovan void l2cap_chan_close(struct l2cap_chan *chan, int reason)
8164519de9aSGustavo F. Padovan {
8174519de9aSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
8184519de9aSGustavo F. Padovan 
8197eafc59eSMarcel Holtmann 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
8204519de9aSGustavo F. Padovan 
82189bc500eSGustavo F. Padovan 	switch (chan->state) {
8224519de9aSGustavo F. Padovan 	case BT_LISTEN:
823c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8244519de9aSGustavo F. Padovan 		break;
8254519de9aSGustavo F. Padovan 
8264519de9aSGustavo F. Padovan 	case BT_CONNECTED:
8274519de9aSGustavo F. Padovan 	case BT_CONFIG:
8287b25c9b3SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
8298d836d71SGustavo Padovan 			__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8305e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, reason);
8314519de9aSGustavo F. Padovan 		} else
8324519de9aSGustavo F. Padovan 			l2cap_chan_del(chan, reason);
8334519de9aSGustavo F. Padovan 		break;
8344519de9aSGustavo F. Padovan 
8354519de9aSGustavo F. Padovan 	case BT_CONNECT2:
836791d60f7SJohan Hedberg 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
837791d60f7SJohan Hedberg 			if (conn->hcon->type == ACL_LINK)
838791d60f7SJohan Hedberg 				l2cap_chan_connect_reject(chan);
83915f02b91SLuiz Augusto von Dentz 			else if (conn->hcon->type == LE_LINK) {
84015f02b91SLuiz Augusto von Dentz 				switch (chan->mode) {
84115f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_LE_FLOWCTL:
84227e2d4c8SJohan Hedberg 					l2cap_chan_le_connect_reject(chan);
84315f02b91SLuiz Augusto von Dentz 					break;
84415f02b91SLuiz Augusto von Dentz 				case L2CAP_MODE_EXT_FLOWCTL:
84515f02b91SLuiz Augusto von Dentz 					l2cap_chan_ecred_connect_reject(chan);
846*9aa9d947SLuiz Augusto von Dentz 					return;
84715f02b91SLuiz Augusto von Dentz 				}
84815f02b91SLuiz Augusto von Dentz 			}
8494519de9aSGustavo F. Padovan 		}
8504519de9aSGustavo F. Padovan 
8514519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8524519de9aSGustavo F. Padovan 		break;
8534519de9aSGustavo F. Padovan 
8544519de9aSGustavo F. Padovan 	case BT_CONNECT:
8554519de9aSGustavo F. Padovan 	case BT_DISCONN:
8564519de9aSGustavo F. Padovan 		l2cap_chan_del(chan, reason);
8574519de9aSGustavo F. Padovan 		break;
8584519de9aSGustavo F. Padovan 
8594519de9aSGustavo F. Padovan 	default:
860c0df7f6eSAndrei Emeltchenko 		chan->ops->teardown(chan, 0);
8614519de9aSGustavo F. Padovan 		break;
8624519de9aSGustavo F. Padovan 	}
8634519de9aSGustavo F. Padovan }
8646b8d4a6aSJukka Rissanen EXPORT_SYMBOL(l2cap_chan_close);
8654519de9aSGustavo F. Padovan 
8664343478fSGustavo F. Padovan static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
8670a708f8fSGustavo F. Padovan {
8686a974b50SMarcel Holtmann 	switch (chan->chan_type) {
8696a974b50SMarcel Holtmann 	case L2CAP_CHAN_RAW:
8704343478fSGustavo F. Padovan 		switch (chan->sec_level) {
8710a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
8727d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
8730a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING_MITM;
8740a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
8750a708f8fSGustavo F. Padovan 			return HCI_AT_DEDICATED_BONDING;
8760a708f8fSGustavo F. Padovan 		default:
8770a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
8780a708f8fSGustavo F. Padovan 		}
8796a974b50SMarcel Holtmann 		break;
8803124b843SMarcel Holtmann 	case L2CAP_CHAN_CONN_LESS:
881dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) {
8823124b843SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_LOW)
8833124b843SMarcel Holtmann 				chan->sec_level = BT_SECURITY_SDP;
8843124b843SMarcel Holtmann 		}
8857d513e92SMarcel Holtmann 		if (chan->sec_level == BT_SECURITY_HIGH ||
8867d513e92SMarcel Holtmann 		    chan->sec_level == BT_SECURITY_FIPS)
8873124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING_MITM;
8883124b843SMarcel Holtmann 		else
8893124b843SMarcel Holtmann 			return HCI_AT_NO_BONDING;
8903124b843SMarcel Holtmann 		break;
8916a974b50SMarcel Holtmann 	case L2CAP_CHAN_CONN_ORIENTED:
892dcf4adbfSJoe Perches 		if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) {
8934343478fSGustavo F. Padovan 			if (chan->sec_level == BT_SECURITY_LOW)
8944343478fSGustavo F. Padovan 				chan->sec_level = BT_SECURITY_SDP;
8950a708f8fSGustavo F. Padovan 
8967d513e92SMarcel Holtmann 			if (chan->sec_level == BT_SECURITY_HIGH ||
8977d513e92SMarcel Holtmann 			    chan->sec_level == BT_SECURITY_FIPS)
8980a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING_MITM;
8990a708f8fSGustavo F. Padovan 			else
9000a708f8fSGustavo F. Padovan 				return HCI_AT_NO_BONDING;
9016a974b50SMarcel Holtmann 		}
90219186c7bSGustavo A. R. Silva 		fallthrough;
90319186c7bSGustavo A. R. Silva 
9046a974b50SMarcel Holtmann 	default:
9054343478fSGustavo F. Padovan 		switch (chan->sec_level) {
9060a708f8fSGustavo F. Padovan 		case BT_SECURITY_HIGH:
9077d513e92SMarcel Holtmann 		case BT_SECURITY_FIPS:
9080a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING_MITM;
9090a708f8fSGustavo F. Padovan 		case BT_SECURITY_MEDIUM:
9100a708f8fSGustavo F. Padovan 			return HCI_AT_GENERAL_BONDING;
9110a708f8fSGustavo F. Padovan 		default:
9120a708f8fSGustavo F. Padovan 			return HCI_AT_NO_BONDING;
9130a708f8fSGustavo F. Padovan 		}
9146a974b50SMarcel Holtmann 		break;
9150a708f8fSGustavo F. Padovan 	}
9160a708f8fSGustavo F. Padovan }
9170a708f8fSGustavo F. Padovan 
9180a708f8fSGustavo F. Padovan /* Service level security */
919e7cafc45SJohan Hedberg int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator)
9200a708f8fSGustavo F. Padovan {
9218c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
9220a708f8fSGustavo F. Padovan 	__u8 auth_type;
9230a708f8fSGustavo F. Padovan 
924a17de2feSJohan Hedberg 	if (conn->hcon->type == LE_LINK)
925a17de2feSJohan Hedberg 		return smp_conn_security(conn->hcon, chan->sec_level);
926a17de2feSJohan Hedberg 
9274343478fSGustavo F. Padovan 	auth_type = l2cap_get_auth_type(chan);
9280a708f8fSGustavo F. Padovan 
929e7cafc45SJohan Hedberg 	return hci_conn_security(conn->hcon, chan->sec_level, auth_type,
930e7cafc45SJohan Hedberg 				 initiator);
9310a708f8fSGustavo F. Padovan }
9320a708f8fSGustavo F. Padovan 
933b5ad8b7fSJohannes Berg static u8 l2cap_get_ident(struct l2cap_conn *conn)
9340a708f8fSGustavo F. Padovan {
9350a708f8fSGustavo F. Padovan 	u8 id;
9360a708f8fSGustavo F. Padovan 
9370a708f8fSGustavo F. Padovan 	/* Get next available identificator.
9380a708f8fSGustavo F. Padovan 	 *    1 - 128 are used by kernel.
9390a708f8fSGustavo F. Padovan 	 *  129 - 199 are reserved.
9400a708f8fSGustavo F. Padovan 	 *  200 - 254 are used by utilities like l2ping, etc.
9410a708f8fSGustavo F. Padovan 	 */
9420a708f8fSGustavo F. Padovan 
9435a54e7c8SMarcel Holtmann 	mutex_lock(&conn->ident_lock);
9440a708f8fSGustavo F. Padovan 
9450a708f8fSGustavo F. Padovan 	if (++conn->tx_ident > 128)
9460a708f8fSGustavo F. Padovan 		conn->tx_ident = 1;
9470a708f8fSGustavo F. Padovan 
9480a708f8fSGustavo F. Padovan 	id = conn->tx_ident;
9490a708f8fSGustavo F. Padovan 
9505a54e7c8SMarcel Holtmann 	mutex_unlock(&conn->ident_lock);
9510a708f8fSGustavo F. Padovan 
9520a708f8fSGustavo F. Padovan 	return id;
9530a708f8fSGustavo F. Padovan }
9540a708f8fSGustavo F. Padovan 
9552d792818SGustavo Padovan static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
9562d792818SGustavo Padovan 			   void *data)
9570a708f8fSGustavo F. Padovan {
9580a708f8fSGustavo F. Padovan 	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
9590a708f8fSGustavo F. Padovan 	u8 flags;
9600a708f8fSGustavo F. Padovan 
9610a708f8fSGustavo F. Padovan 	BT_DBG("code 0x%2.2x", code);
9620a708f8fSGustavo F. Padovan 
9630a708f8fSGustavo F. Padovan 	if (!skb)
9640a708f8fSGustavo F. Padovan 		return;
9650a708f8fSGustavo F. Padovan 
966f6af675eSSteven Walter 	/* Use NO_FLUSH if supported or we have an LE link (which does
967f6af675eSSteven Walter 	 * not support auto-flushing packets) */
968f6af675eSSteven Walter 	if (lmp_no_flush_capable(conn->hcon->hdev) ||
969f6af675eSSteven Walter 	    conn->hcon->type == LE_LINK)
9700a708f8fSGustavo F. Padovan 		flags = ACL_START_NO_FLUSH;
9710a708f8fSGustavo F. Padovan 	else
9720a708f8fSGustavo F. Padovan 		flags = ACL_START;
9730a708f8fSGustavo F. Padovan 
97414b12d0bSJaikumar Ganesh 	bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
9755e59b791SLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
97614b12d0bSJaikumar Ganesh 
97773d80debSLuiz Augusto von Dentz 	hci_send_acl(conn->hchan, skb, flags);
9780a708f8fSGustavo F. Padovan }
9790a708f8fSGustavo F. Padovan 
98002b0fbb9SMat Martineau static bool __chan_is_moving(struct l2cap_chan *chan)
98102b0fbb9SMat Martineau {
98202b0fbb9SMat Martineau 	return chan->move_state != L2CAP_MOVE_STABLE &&
98302b0fbb9SMat Martineau 	       chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
98402b0fbb9SMat Martineau }
98502b0fbb9SMat Martineau 
98673d80debSLuiz Augusto von Dentz static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
98773d80debSLuiz Augusto von Dentz {
98873d80debSLuiz Augusto von Dentz 	struct hci_conn *hcon = chan->conn->hcon;
98973d80debSLuiz Augusto von Dentz 	u16 flags;
99073d80debSLuiz Augusto von Dentz 
99173d80debSLuiz Augusto von Dentz 	BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
99273d80debSLuiz Augusto von Dentz 	       skb->priority);
99373d80debSLuiz Augusto von Dentz 
994d5f8a75dSMat Martineau 	if (chan->hs_hcon && !__chan_is_moving(chan)) {
995d5f8a75dSMat Martineau 		if (chan->hs_hchan)
996d5f8a75dSMat Martineau 			hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
997d5f8a75dSMat Martineau 		else
998d5f8a75dSMat Martineau 			kfree_skb(skb);
999d5f8a75dSMat Martineau 
1000d5f8a75dSMat Martineau 		return;
1001d5f8a75dSMat Martineau 	}
1002d5f8a75dSMat Martineau 
1003f6af675eSSteven Walter 	/* Use NO_FLUSH for LE links (where this is the only option) or
1004f6af675eSSteven Walter 	 * if the BR/EDR link supports it and flushing has not been
1005f6af675eSSteven Walter 	 * explicitly requested (through FLAG_FLUSHABLE).
1006f6af675eSSteven Walter 	 */
1007f6af675eSSteven Walter 	if (hcon->type == LE_LINK ||
1008f6af675eSSteven Walter 	    (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
1009f6af675eSSteven Walter 	     lmp_no_flush_capable(hcon->hdev)))
101073d80debSLuiz Augusto von Dentz 		flags = ACL_START_NO_FLUSH;
101173d80debSLuiz Augusto von Dentz 	else
101273d80debSLuiz Augusto von Dentz 		flags = ACL_START;
101373d80debSLuiz Augusto von Dentz 
101473d80debSLuiz Augusto von Dentz 	bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
101573d80debSLuiz Augusto von Dentz 	hci_send_acl(chan->conn->hchan, skb, flags);
10160a708f8fSGustavo F. Padovan }
10170a708f8fSGustavo F. Padovan 
1018b5c6aaedSMat Martineau static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
1019b5c6aaedSMat Martineau {
1020b5c6aaedSMat Martineau 	control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
1021b5c6aaedSMat Martineau 	control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
1022b5c6aaedSMat Martineau 
1023b5c6aaedSMat Martineau 	if (enh & L2CAP_CTRL_FRAME_TYPE) {
1024b5c6aaedSMat Martineau 		/* S-Frame */
1025b5c6aaedSMat Martineau 		control->sframe = 1;
1026b5c6aaedSMat Martineau 		control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
1027b5c6aaedSMat Martineau 		control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_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 = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
1035b5c6aaedSMat Martineau 		control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
1036b5c6aaedSMat Martineau 
1037b5c6aaedSMat Martineau 		control->poll = 0;
1038b5c6aaedSMat Martineau 		control->super = 0;
1039b5c6aaedSMat Martineau 	}
1040b5c6aaedSMat Martineau }
1041b5c6aaedSMat Martineau 
1042b5c6aaedSMat Martineau static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
1043b5c6aaedSMat Martineau {
1044b5c6aaedSMat Martineau 	control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1045b5c6aaedSMat Martineau 	control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
1046b5c6aaedSMat Martineau 
1047b5c6aaedSMat Martineau 	if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
1048b5c6aaedSMat Martineau 		/* S-Frame */
1049b5c6aaedSMat Martineau 		control->sframe = 1;
1050b5c6aaedSMat Martineau 		control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
1051b5c6aaedSMat Martineau 		control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
1052b5c6aaedSMat Martineau 
1053b5c6aaedSMat Martineau 		control->sar = 0;
1054b5c6aaedSMat Martineau 		control->txseq = 0;
1055b5c6aaedSMat Martineau 	} else {
1056b5c6aaedSMat Martineau 		/* I-Frame */
1057b5c6aaedSMat Martineau 		control->sframe = 0;
1058b5c6aaedSMat Martineau 		control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
1059b5c6aaedSMat Martineau 		control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1060b5c6aaedSMat Martineau 
1061b5c6aaedSMat Martineau 		control->poll = 0;
1062b5c6aaedSMat Martineau 		control->super = 0;
1063b5c6aaedSMat Martineau 	}
1064b5c6aaedSMat Martineau }
1065b5c6aaedSMat Martineau 
1066b5c6aaedSMat Martineau static inline void __unpack_control(struct l2cap_chan *chan,
1067b5c6aaedSMat Martineau 				    struct sk_buff *skb)
1068b5c6aaedSMat Martineau {
1069b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1070b5c6aaedSMat Martineau 		__unpack_extended_control(get_unaligned_le32(skb->data),
1071a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1072cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_EXT_CTRL_SIZE);
1073b5c6aaedSMat Martineau 	} else {
1074b5c6aaedSMat Martineau 		__unpack_enhanced_control(get_unaligned_le16(skb->data),
1075a4368ff3SJohan Hedberg 					  &bt_cb(skb)->l2cap);
1076cec8ab6eSMat Martineau 		skb_pull(skb, L2CAP_ENH_CTRL_SIZE);
1077b5c6aaedSMat Martineau 	}
1078b5c6aaedSMat Martineau }
1079b5c6aaedSMat Martineau 
1080b5c6aaedSMat Martineau static u32 __pack_extended_control(struct l2cap_ctrl *control)
1081b5c6aaedSMat Martineau {
1082b5c6aaedSMat Martineau 	u32 packed;
1083b5c6aaedSMat Martineau 
1084b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
1085b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
1086b5c6aaedSMat Martineau 
1087b5c6aaedSMat Martineau 	if (control->sframe) {
1088b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
1089b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
1090b5c6aaedSMat Martineau 		packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
1091b5c6aaedSMat Martineau 	} else {
1092b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
1093b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
1094b5c6aaedSMat Martineau 	}
1095b5c6aaedSMat Martineau 
1096b5c6aaedSMat Martineau 	return packed;
1097b5c6aaedSMat Martineau }
1098b5c6aaedSMat Martineau 
1099b5c6aaedSMat Martineau static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
1100b5c6aaedSMat Martineau {
1101b5c6aaedSMat Martineau 	u16 packed;
1102b5c6aaedSMat Martineau 
1103b5c6aaedSMat Martineau 	packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
1104b5c6aaedSMat Martineau 	packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
1105b5c6aaedSMat Martineau 
1106b5c6aaedSMat Martineau 	if (control->sframe) {
1107b5c6aaedSMat Martineau 		packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
1108b5c6aaedSMat Martineau 		packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
1109b5c6aaedSMat Martineau 		packed |= L2CAP_CTRL_FRAME_TYPE;
1110b5c6aaedSMat Martineau 	} else {
1111b5c6aaedSMat Martineau 		packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
1112b5c6aaedSMat Martineau 		packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
1113b5c6aaedSMat Martineau 	}
1114b5c6aaedSMat Martineau 
1115b5c6aaedSMat Martineau 	return packed;
1116b5c6aaedSMat Martineau }
1117b5c6aaedSMat Martineau 
1118b5c6aaedSMat Martineau static inline void __pack_control(struct l2cap_chan *chan,
1119b5c6aaedSMat Martineau 				  struct l2cap_ctrl *control,
1120b5c6aaedSMat Martineau 				  struct sk_buff *skb)
1121b5c6aaedSMat Martineau {
1122b5c6aaedSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
1123b5c6aaedSMat Martineau 		put_unaligned_le32(__pack_extended_control(control),
1124b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1125b5c6aaedSMat Martineau 	} else {
1126b5c6aaedSMat Martineau 		put_unaligned_le16(__pack_enhanced_control(control),
1127b5c6aaedSMat Martineau 				   skb->data + L2CAP_HDR_SIZE);
1128b5c6aaedSMat Martineau 	}
1129b5c6aaedSMat Martineau }
1130b5c6aaedSMat Martineau 
1131ba7aa64fSGustavo Padovan static inline unsigned int __ertm_hdr_size(struct l2cap_chan *chan)
1132ba7aa64fSGustavo Padovan {
1133ba7aa64fSGustavo Padovan 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1134ba7aa64fSGustavo Padovan 		return L2CAP_EXT_HDR_SIZE;
1135ba7aa64fSGustavo Padovan 	else
1136ba7aa64fSGustavo Padovan 		return L2CAP_ENH_HDR_SIZE;
1137ba7aa64fSGustavo Padovan }
1138ba7aa64fSGustavo Padovan 
1139a67d7f6fSMat Martineau static struct sk_buff *l2cap_create_sframe_pdu(struct l2cap_chan *chan,
1140a67d7f6fSMat Martineau 					       u32 control)
11410a708f8fSGustavo F. Padovan {
11420a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
11430a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
1144ba7aa64fSGustavo Padovan 	int hlen = __ertm_hdr_size(chan);
11450a708f8fSGustavo F. Padovan 
11460a708f8fSGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
114703a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
11480a708f8fSGustavo F. Padovan 
1149a67d7f6fSMat Martineau 	skb = bt_skb_alloc(hlen, GFP_KERNEL);
11500a708f8fSGustavo F. Padovan 
11510a708f8fSGustavo F. Padovan 	if (!skb)
1152a67d7f6fSMat Martineau 		return ERR_PTR(-ENOMEM);
11530a708f8fSGustavo F. Padovan 
11544df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
11550a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
1156fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
115788843ab0SAndrei Emeltchenko 
1158a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1159a67d7f6fSMat Martineau 		put_unaligned_le32(control, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
1160a67d7f6fSMat Martineau 	else
1161a67d7f6fSMat Martineau 		put_unaligned_le16(control, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
11620a708f8fSGustavo F. Padovan 
116347d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
1164a67d7f6fSMat Martineau 		u16 fcs = crc16(0, (u8 *)skb->data, skb->len);
116503a51213SAndrei Emeltchenko 		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
11660a708f8fSGustavo F. Padovan 	}
11670a708f8fSGustavo F. Padovan 
116873d80debSLuiz Augusto von Dentz 	skb->priority = HCI_PRIO_MAX;
1169a67d7f6fSMat Martineau 	return skb;
1170a67d7f6fSMat Martineau }
1171a67d7f6fSMat Martineau 
1172a67d7f6fSMat Martineau static void l2cap_send_sframe(struct l2cap_chan *chan,
1173a67d7f6fSMat Martineau 			      struct l2cap_ctrl *control)
1174a67d7f6fSMat Martineau {
1175a67d7f6fSMat Martineau 	struct sk_buff *skb;
1176a67d7f6fSMat Martineau 	u32 control_field;
1177a67d7f6fSMat Martineau 
1178a67d7f6fSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
1179a67d7f6fSMat Martineau 
1180a67d7f6fSMat Martineau 	if (!control->sframe)
1181a67d7f6fSMat Martineau 		return;
1182a67d7f6fSMat Martineau 
1183b99e13adSMat Martineau 	if (__chan_is_moving(chan))
1184b99e13adSMat Martineau 		return;
1185b99e13adSMat Martineau 
1186a67d7f6fSMat Martineau 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
1187a67d7f6fSMat Martineau 	    !control->poll)
1188a67d7f6fSMat Martineau 		control->final = 1;
1189a67d7f6fSMat Martineau 
1190a67d7f6fSMat Martineau 	if (control->super == L2CAP_SUPER_RR)
1191a67d7f6fSMat Martineau 		clear_bit(CONN_RNR_SENT, &chan->conn_state);
1192a67d7f6fSMat Martineau 	else if (control->super == L2CAP_SUPER_RNR)
1193a67d7f6fSMat Martineau 		set_bit(CONN_RNR_SENT, &chan->conn_state);
1194a67d7f6fSMat Martineau 
1195a67d7f6fSMat Martineau 	if (control->super != L2CAP_SUPER_SREJ) {
1196a67d7f6fSMat Martineau 		chan->last_acked_seq = control->reqseq;
1197a67d7f6fSMat Martineau 		__clear_ack_timer(chan);
1198a67d7f6fSMat Martineau 	}
1199a67d7f6fSMat Martineau 
1200a67d7f6fSMat Martineau 	BT_DBG("reqseq %d, final %d, poll %d, super %d", control->reqseq,
1201a67d7f6fSMat Martineau 	       control->final, control->poll, control->super);
1202a67d7f6fSMat Martineau 
1203a67d7f6fSMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
1204a67d7f6fSMat Martineau 		control_field = __pack_extended_control(control);
1205a67d7f6fSMat Martineau 	else
1206a67d7f6fSMat Martineau 		control_field = __pack_enhanced_control(control);
1207a67d7f6fSMat Martineau 
1208a67d7f6fSMat Martineau 	skb = l2cap_create_sframe_pdu(chan, control_field);
1209a67d7f6fSMat Martineau 	if (!IS_ERR(skb))
121073d80debSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb);
12110a708f8fSGustavo F. Padovan }
12120a708f8fSGustavo F. Padovan 
1213c9e3d5e0SMat Martineau static void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, bool poll)
12140a708f8fSGustavo F. Padovan {
1215c9e3d5e0SMat Martineau 	struct l2cap_ctrl control;
12160a708f8fSGustavo F. Padovan 
1217c9e3d5e0SMat Martineau 	BT_DBG("chan %p, poll %d", chan, poll);
1218c9e3d5e0SMat Martineau 
1219c9e3d5e0SMat Martineau 	memset(&control, 0, sizeof(control));
1220c9e3d5e0SMat Martineau 	control.sframe = 1;
1221c9e3d5e0SMat Martineau 	control.poll = poll;
1222c9e3d5e0SMat Martineau 
1223c9e3d5e0SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
1224c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RNR;
1225c9e3d5e0SMat Martineau 	else
1226c9e3d5e0SMat Martineau 		control.super = L2CAP_SUPER_RR;
1227c9e3d5e0SMat Martineau 
1228c9e3d5e0SMat Martineau 	control.reqseq = chan->buffer_seq;
1229c9e3d5e0SMat Martineau 	l2cap_send_sframe(chan, &control);
12300a708f8fSGustavo F. Padovan }
12310a708f8fSGustavo F. Padovan 
1232b4450035SGustavo F. Padovan static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
12330a708f8fSGustavo F. Padovan {
12345ff6f34dSJohan Hedberg 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
12355ff6f34dSJohan Hedberg 		return true;
12365ff6f34dSJohan Hedberg 
1237c1360a1cSGustavo F. Padovan 	return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
12380a708f8fSGustavo F. Padovan }
12390a708f8fSGustavo F. Padovan 
124093c3e8f5SAndrei Emeltchenko static bool __amp_capable(struct l2cap_chan *chan)
124193c3e8f5SAndrei Emeltchenko {
124293c3e8f5SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12431df7b17aSMarcel Holtmann 	struct hci_dev *hdev;
12441df7b17aSMarcel Holtmann 	bool amp_available = false;
124593c3e8f5SAndrei Emeltchenko 
12460bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
12471df7b17aSMarcel Holtmann 		return false;
12481df7b17aSMarcel Holtmann 
12490bd49fc7SJohan Hedberg 	if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
12501df7b17aSMarcel Holtmann 		return false;
12511df7b17aSMarcel Holtmann 
12521df7b17aSMarcel Holtmann 	read_lock(&hci_dev_list_lock);
12531df7b17aSMarcel Holtmann 	list_for_each_entry(hdev, &hci_dev_list, list) {
12541df7b17aSMarcel Holtmann 		if (hdev->amp_type != AMP_TYPE_BREDR &&
12551df7b17aSMarcel Holtmann 		    test_bit(HCI_UP, &hdev->flags)) {
12561df7b17aSMarcel Holtmann 			amp_available = true;
12571df7b17aSMarcel Holtmann 			break;
12581df7b17aSMarcel Holtmann 		}
12591df7b17aSMarcel Holtmann 	}
12601df7b17aSMarcel Holtmann 	read_unlock(&hci_dev_list_lock);
12611df7b17aSMarcel Holtmann 
12621df7b17aSMarcel Holtmann 	if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
12631df7b17aSMarcel Holtmann 		return amp_available;
1264848566b3SMarcel Holtmann 
126593c3e8f5SAndrei Emeltchenko 	return false;
126693c3e8f5SAndrei Emeltchenko }
126793c3e8f5SAndrei Emeltchenko 
12685ce66b59SAndrei Emeltchenko static bool l2cap_check_efs(struct l2cap_chan *chan)
12695ce66b59SAndrei Emeltchenko {
12705ce66b59SAndrei Emeltchenko 	/* Check EFS parameters */
12715ce66b59SAndrei Emeltchenko 	return true;
12725ce66b59SAndrei Emeltchenko }
12735ce66b59SAndrei Emeltchenko 
12742766be48SAndrei Emeltchenko void l2cap_send_conn_req(struct l2cap_chan *chan)
12759b27f350SAndrei Emeltchenko {
12769b27f350SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
12779b27f350SAndrei Emeltchenko 	struct l2cap_conn_req req;
12789b27f350SAndrei Emeltchenko 
12799b27f350SAndrei Emeltchenko 	req.scid = cpu_to_le16(chan->scid);
12809b27f350SAndrei Emeltchenko 	req.psm  = chan->psm;
12819b27f350SAndrei Emeltchenko 
12829b27f350SAndrei Emeltchenko 	chan->ident = l2cap_get_ident(conn);
12839b27f350SAndrei Emeltchenko 
12849b27f350SAndrei Emeltchenko 	set_bit(CONF_CONNECT_PEND, &chan->conf_state);
12859b27f350SAndrei Emeltchenko 
12869b27f350SAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
12879b27f350SAndrei Emeltchenko }
12889b27f350SAndrei Emeltchenko 
12898eb200bdSMat Martineau static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
12908eb200bdSMat Martineau {
12918eb200bdSMat Martineau 	struct l2cap_create_chan_req req;
12928eb200bdSMat Martineau 	req.scid = cpu_to_le16(chan->scid);
12938eb200bdSMat Martineau 	req.psm  = chan->psm;
12948eb200bdSMat Martineau 	req.amp_id = amp_id;
12958eb200bdSMat Martineau 
12968eb200bdSMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
12978eb200bdSMat Martineau 
12988eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
12998eb200bdSMat Martineau 		       sizeof(req), &req);
13008eb200bdSMat Martineau }
13018eb200bdSMat Martineau 
130202b0fbb9SMat Martineau static void l2cap_move_setup(struct l2cap_chan *chan)
130302b0fbb9SMat Martineau {
130402b0fbb9SMat Martineau 	struct sk_buff *skb;
130502b0fbb9SMat Martineau 
130602b0fbb9SMat Martineau 	BT_DBG("chan %p", chan);
130702b0fbb9SMat Martineau 
130802b0fbb9SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
130902b0fbb9SMat Martineau 		return;
131002b0fbb9SMat Martineau 
131102b0fbb9SMat Martineau 	__clear_retrans_timer(chan);
131202b0fbb9SMat Martineau 	__clear_monitor_timer(chan);
131302b0fbb9SMat Martineau 	__clear_ack_timer(chan);
131402b0fbb9SMat Martineau 
131502b0fbb9SMat Martineau 	chan->retry_count = 0;
131602b0fbb9SMat Martineau 	skb_queue_walk(&chan->tx_q, skb) {
1317a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.retries)
1318a4368ff3SJohan Hedberg 			bt_cb(skb)->l2cap.retries = 1;
131902b0fbb9SMat Martineau 		else
132002b0fbb9SMat Martineau 			break;
132102b0fbb9SMat Martineau 	}
132202b0fbb9SMat Martineau 
132302b0fbb9SMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
132402b0fbb9SMat Martineau 
132502b0fbb9SMat Martineau 	clear_bit(CONN_REJ_ACT, &chan->conn_state);
132602b0fbb9SMat Martineau 	clear_bit(CONN_SREJ_ACT, &chan->conn_state);
132702b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
132802b0fbb9SMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
132902b0fbb9SMat Martineau 	skb_queue_purge(&chan->srej_q);
133002b0fbb9SMat Martineau 
133102b0fbb9SMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
133202b0fbb9SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_MOVE;
133302b0fbb9SMat Martineau 
133402b0fbb9SMat Martineau 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
133502b0fbb9SMat Martineau }
133602b0fbb9SMat Martineau 
13375f3847a4SMat Martineau static void l2cap_move_done(struct l2cap_chan *chan)
13385f3847a4SMat Martineau {
13395f3847a4SMat Martineau 	u8 move_role = chan->move_role;
13405f3847a4SMat Martineau 	BT_DBG("chan %p", chan);
13415f3847a4SMat Martineau 
13425f3847a4SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
13435f3847a4SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
13445f3847a4SMat Martineau 
13455f3847a4SMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
13465f3847a4SMat Martineau 		return;
13475f3847a4SMat Martineau 
13485f3847a4SMat Martineau 	switch (move_role) {
13495f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
13505f3847a4SMat Martineau 		l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
13515f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_F;
13525f3847a4SMat Martineau 		break;
13535f3847a4SMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
13545f3847a4SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_WAIT_P;
13555f3847a4SMat Martineau 		break;
13565f3847a4SMat Martineau 	}
13575f3847a4SMat Martineau }
13585f3847a4SMat Martineau 
13599f0caeb1SVinicius Costa Gomes static void l2cap_chan_ready(struct l2cap_chan *chan)
13609f0caeb1SVinicius Costa Gomes {
1361315917e0SJohan Hedberg 	/* The channel may have already been flagged as connected in
1362315917e0SJohan Hedberg 	 * case of receiving data before the L2CAP info req/rsp
1363315917e0SJohan Hedberg 	 * procedure is complete.
1364315917e0SJohan Hedberg 	 */
1365315917e0SJohan Hedberg 	if (chan->state == BT_CONNECTED)
1366315917e0SJohan Hedberg 		return;
1367315917e0SJohan Hedberg 
13682827011fSMat Martineau 	/* This clears all conf flags, including CONF_NOT_COMPLETE */
13699f0caeb1SVinicius Costa Gomes 	chan->conf_state = 0;
13709f0caeb1SVinicius Costa Gomes 	__clear_chan_timer(chan);
13719f0caeb1SVinicius Costa Gomes 
137215f02b91SLuiz Augusto von Dentz 	switch (chan->mode) {
137315f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_LE_FLOWCTL:
137415f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
137515f02b91SLuiz Augusto von Dentz 		if (!chan->tx_credits)
13760ce43ce6SJohan Hedberg 			chan->ops->suspend(chan);
137715f02b91SLuiz Augusto von Dentz 		break;
137815f02b91SLuiz Augusto von Dentz 	}
1379177f8f2bSJohan Hedberg 
138054a59aa2SAndrei Emeltchenko 	chan->state = BT_CONNECTED;
13819f0caeb1SVinicius Costa Gomes 
138254a59aa2SAndrei Emeltchenko 	chan->ops->ready(chan);
13839f0caeb1SVinicius Costa Gomes }
13849f0caeb1SVinicius Costa Gomes 
1385f1496deeSJohan Hedberg static void l2cap_le_connect(struct l2cap_chan *chan)
1386f1496deeSJohan Hedberg {
1387f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1388f1496deeSJohan Hedberg 	struct l2cap_le_conn_req req;
1389f1496deeSJohan Hedberg 
1390595177f3SJohan Hedberg 	if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
1391595177f3SJohan Hedberg 		return;
1392595177f3SJohan Hedberg 
13934b6e228eSLuiz Augusto von Dentz 	if (!chan->imtu)
13944b6e228eSLuiz Augusto von Dentz 		chan->imtu = chan->conn->mtu;
13954b6e228eSLuiz Augusto von Dentz 
1396ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, 0);
1397fe149310SLuiz Augusto von Dentz 
1398a5133fe8SXiaohui Zhang 	memset(&req, 0, sizeof(req));
1399f1496deeSJohan Hedberg 	req.psm     = chan->psm;
1400f1496deeSJohan Hedberg 	req.scid    = cpu_to_le16(chan->scid);
1401f1496deeSJohan Hedberg 	req.mtu     = cpu_to_le16(chan->imtu);
14023916aed8SJohan Hedberg 	req.mps     = cpu_to_le16(chan->mps);
14030cd75f7eSJohan Hedberg 	req.credits = cpu_to_le16(chan->rx_credits);
1404f1496deeSJohan Hedberg 
1405f1496deeSJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
1406f1496deeSJohan Hedberg 
1407f1496deeSJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
1408f1496deeSJohan Hedberg 		       sizeof(req), &req);
1409f1496deeSJohan Hedberg }
1410f1496deeSJohan Hedberg 
1411da49b602SLuiz Augusto von Dentz struct l2cap_ecred_conn_data {
141215f02b91SLuiz Augusto von Dentz 	struct {
141315f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_req req;
1414da49b602SLuiz Augusto von Dentz 		__le16 scid[5];
141515f02b91SLuiz Augusto von Dentz 	} __packed pdu;
1416da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
1417da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1418da49b602SLuiz Augusto von Dentz 	int count;
1419da49b602SLuiz Augusto von Dentz };
1420da49b602SLuiz Augusto von Dentz 
1421da49b602SLuiz Augusto von Dentz static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data)
1422da49b602SLuiz Augusto von Dentz {
1423da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data *conn = data;
1424da49b602SLuiz Augusto von Dentz 	struct pid *pid;
1425da49b602SLuiz Augusto von Dentz 
1426da49b602SLuiz Augusto von Dentz 	if (chan == conn->chan)
1427da49b602SLuiz Augusto von Dentz 		return;
1428da49b602SLuiz Augusto von Dentz 
1429da49b602SLuiz Augusto von Dentz 	if (!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
1430da49b602SLuiz Augusto von Dentz 		return;
1431da49b602SLuiz Augusto von Dentz 
1432da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
1433da49b602SLuiz Augusto von Dentz 
1434da49b602SLuiz Augusto von Dentz 	/* Only add deferred channels with the same PID/PSM */
1435da49b602SLuiz Augusto von Dentz 	if (conn->pid != pid || chan->psm != conn->chan->psm || chan->ident ||
1436da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
1437da49b602SLuiz Augusto von Dentz 		return;
143815f02b91SLuiz Augusto von Dentz 
143915f02b91SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
144015f02b91SLuiz Augusto von Dentz 		return;
144115f02b91SLuiz Augusto von Dentz 
144215f02b91SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
144315f02b91SLuiz Augusto von Dentz 
1444da49b602SLuiz Augusto von Dentz 	/* Set the same ident so we can match on the rsp */
1445da49b602SLuiz Augusto von Dentz 	chan->ident = conn->chan->ident;
1446da49b602SLuiz Augusto von Dentz 
1447da49b602SLuiz Augusto von Dentz 	/* Include all channels deferred */
1448da49b602SLuiz Augusto von Dentz 	conn->pdu.scid[conn->count] = cpu_to_le16(chan->scid);
1449da49b602SLuiz Augusto von Dentz 
1450da49b602SLuiz Augusto von Dentz 	conn->count++;
1451da49b602SLuiz Augusto von Dentz }
1452da49b602SLuiz Augusto von Dentz 
1453da49b602SLuiz Augusto von Dentz static void l2cap_ecred_connect(struct l2cap_chan *chan)
1454da49b602SLuiz Augusto von Dentz {
1455da49b602SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
1456da49b602SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_data data;
1457da49b602SLuiz Augusto von Dentz 
1458da49b602SLuiz Augusto von Dentz 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
1459da49b602SLuiz Augusto von Dentz 		return;
1460da49b602SLuiz Augusto von Dentz 
1461da49b602SLuiz Augusto von Dentz 	if (test_and_set_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
1462da49b602SLuiz Augusto von Dentz 		return;
1463da49b602SLuiz Augusto von Dentz 
1464da49b602SLuiz Augusto von Dentz 	l2cap_ecred_init(chan, 0);
1465da49b602SLuiz Augusto von Dentz 
1466d3715b23SMinghao Chi (CGEL ZTE) 	memset(&data, 0, sizeof(data));
1467da49b602SLuiz Augusto von Dentz 	data.pdu.req.psm     = chan->psm;
1468da49b602SLuiz Augusto von Dentz 	data.pdu.req.mtu     = cpu_to_le16(chan->imtu);
1469da49b602SLuiz Augusto von Dentz 	data.pdu.req.mps     = cpu_to_le16(chan->mps);
1470da49b602SLuiz Augusto von Dentz 	data.pdu.req.credits = cpu_to_le16(chan->rx_credits);
1471da49b602SLuiz Augusto von Dentz 	data.pdu.scid[0]     = cpu_to_le16(chan->scid);
147215f02b91SLuiz Augusto von Dentz 
147315f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
1474da49b602SLuiz Augusto von Dentz 
1475da49b602SLuiz Augusto von Dentz 	data.count = 1;
1476da49b602SLuiz Augusto von Dentz 	data.chan = chan;
1477da49b602SLuiz Augusto von Dentz 	data.pid = chan->ops->get_peer_pid(chan);
1478da49b602SLuiz Augusto von Dentz 
1479da49b602SLuiz Augusto von Dentz 	__l2cap_chan_list(conn, l2cap_ecred_defer_connect, &data);
148015f02b91SLuiz Augusto von Dentz 
148115f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_CONN_REQ,
1482da49b602SLuiz Augusto von Dentz 		       sizeof(data.pdu.req) + data.count * sizeof(__le16),
1483da49b602SLuiz Augusto von Dentz 		       &data.pdu);
148415f02b91SLuiz Augusto von Dentz }
148515f02b91SLuiz Augusto von Dentz 
1486f1496deeSJohan Hedberg static void l2cap_le_start(struct l2cap_chan *chan)
1487f1496deeSJohan Hedberg {
1488f1496deeSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1489f1496deeSJohan Hedberg 
1490f1496deeSJohan Hedberg 	if (!smp_conn_security(conn->hcon, chan->sec_level))
1491f1496deeSJohan Hedberg 		return;
1492f1496deeSJohan Hedberg 
1493f1496deeSJohan Hedberg 	if (!chan->psm) {
1494f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
1495f1496deeSJohan Hedberg 		return;
1496f1496deeSJohan Hedberg 	}
1497f1496deeSJohan Hedberg 
149815f02b91SLuiz Augusto von Dentz 	if (chan->state == BT_CONNECT) {
149915f02b91SLuiz Augusto von Dentz 		if (chan->mode == L2CAP_MODE_EXT_FLOWCTL)
150015f02b91SLuiz Augusto von Dentz 			l2cap_ecred_connect(chan);
150115f02b91SLuiz Augusto von Dentz 		else
1502f1496deeSJohan Hedberg 			l2cap_le_connect(chan);
1503f1496deeSJohan Hedberg 	}
150415f02b91SLuiz Augusto von Dentz }
1505f1496deeSJohan Hedberg 
150693c3e8f5SAndrei Emeltchenko static void l2cap_start_connection(struct l2cap_chan *chan)
150793c3e8f5SAndrei Emeltchenko {
150893c3e8f5SAndrei Emeltchenko 	if (__amp_capable(chan)) {
150993c3e8f5SAndrei Emeltchenko 		BT_DBG("chan %p AMP capable: discover AMPs", chan);
151093c3e8f5SAndrei Emeltchenko 		a2mp_discover_amp(chan);
1511f1496deeSJohan Hedberg 	} else if (chan->conn->hcon->type == LE_LINK) {
1512f1496deeSJohan Hedberg 		l2cap_le_start(chan);
151393c3e8f5SAndrei Emeltchenko 	} else {
151493c3e8f5SAndrei Emeltchenko 		l2cap_send_conn_req(chan);
151593c3e8f5SAndrei Emeltchenko 	}
151693c3e8f5SAndrei Emeltchenko }
151793c3e8f5SAndrei Emeltchenko 
1518aeaeb4bbSJohan Hedberg static void l2cap_request_info(struct l2cap_conn *conn)
15190a708f8fSGustavo F. Padovan {
15200a708f8fSGustavo F. Padovan 	struct l2cap_info_req req;
1521aeaeb4bbSJohan Hedberg 
1522aeaeb4bbSJohan Hedberg 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1523aeaeb4bbSJohan Hedberg 		return;
1524aeaeb4bbSJohan Hedberg 
1525dcf4adbfSJoe Perches 	req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
15260a708f8fSGustavo F. Padovan 
15270a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
15280a708f8fSGustavo F. Padovan 	conn->info_ident = l2cap_get_ident(conn);
15290a708f8fSGustavo F. Padovan 
1530ba13ccd9SMarcel Holtmann 	schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
15310a708f8fSGustavo F. Padovan 
15322d792818SGustavo Padovan 	l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
15332d792818SGustavo Padovan 		       sizeof(req), &req);
15340a708f8fSGustavo F. Padovan }
1535aeaeb4bbSJohan Hedberg 
1536693cd8ceSMarcel Holtmann static bool l2cap_check_enc_key_size(struct hci_conn *hcon)
1537693cd8ceSMarcel Holtmann {
1538693cd8ceSMarcel Holtmann 	/* The minimum encryption key size needs to be enforced by the
1539693cd8ceSMarcel Holtmann 	 * host stack before establishing any L2CAP connections. The
1540693cd8ceSMarcel Holtmann 	 * specification in theory allows a minimum of 1, but to align
1541693cd8ceSMarcel Holtmann 	 * BR/EDR and LE transports, a minimum of 7 is chosen.
1542693cd8ceSMarcel Holtmann 	 *
1543693cd8ceSMarcel Holtmann 	 * This check might also be called for unencrypted connections
1544693cd8ceSMarcel Holtmann 	 * that have no key size requirements. Ensure that the link is
1545693cd8ceSMarcel Holtmann 	 * actually encrypted before enforcing a key size.
1546693cd8ceSMarcel Holtmann 	 */
1547288c0697SArchie Pusaka 	int min_key_size = hcon->hdev->min_enc_key_size;
1548288c0697SArchie Pusaka 
1549288c0697SArchie Pusaka 	/* On FIPS security level, key size must be 16 bytes */
1550288c0697SArchie Pusaka 	if (hcon->sec_level == BT_SECURITY_FIPS)
1551288c0697SArchie Pusaka 		min_key_size = 16;
1552288c0697SArchie Pusaka 
1553693cd8ceSMarcel Holtmann 	return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) ||
1554288c0697SArchie Pusaka 		hcon->enc_key_size >= min_key_size);
1555693cd8ceSMarcel Holtmann }
1556693cd8ceSMarcel Holtmann 
1557aeaeb4bbSJohan Hedberg static void l2cap_do_start(struct l2cap_chan *chan)
1558aeaeb4bbSJohan Hedberg {
1559aeaeb4bbSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
1560aeaeb4bbSJohan Hedberg 
1561aeaeb4bbSJohan Hedberg 	if (conn->hcon->type == LE_LINK) {
1562aeaeb4bbSJohan Hedberg 		l2cap_le_start(chan);
1563aeaeb4bbSJohan Hedberg 		return;
1564aeaeb4bbSJohan Hedberg 	}
1565aeaeb4bbSJohan Hedberg 
1566aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)) {
1567aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1568aeaeb4bbSJohan Hedberg 		return;
1569aeaeb4bbSJohan Hedberg 	}
1570aeaeb4bbSJohan Hedberg 
1571aeaeb4bbSJohan Hedberg 	if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
1572aeaeb4bbSJohan Hedberg 		return;
1573aeaeb4bbSJohan Hedberg 
1574693cd8ceSMarcel Holtmann 	if (!l2cap_chan_check_security(chan, true) ||
1575693cd8ceSMarcel Holtmann 	    !__l2cap_no_conn_pending(chan))
1576693cd8ceSMarcel Holtmann 		return;
1577693cd8ceSMarcel Holtmann 
1578693cd8ceSMarcel Holtmann 	if (l2cap_check_enc_key_size(conn->hcon))
1579aeaeb4bbSJohan Hedberg 		l2cap_start_connection(chan);
1580693cd8ceSMarcel Holtmann 	else
1581693cd8ceSMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
15820a708f8fSGustavo F. Padovan }
15830a708f8fSGustavo F. Padovan 
15840a708f8fSGustavo F. Padovan static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
15850a708f8fSGustavo F. Padovan {
15860a708f8fSGustavo F. Padovan 	u32 local_feat_mask = l2cap_feat_mask;
15870a708f8fSGustavo F. Padovan 	if (!disable_ertm)
15880a708f8fSGustavo F. Padovan 		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
15890a708f8fSGustavo F. Padovan 
15900a708f8fSGustavo F. Padovan 	switch (mode) {
15910a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
15920a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
15930a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
15940a708f8fSGustavo F. Padovan 		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
15950a708f8fSGustavo F. Padovan 	default:
15960a708f8fSGustavo F. Padovan 		return 0x00;
15970a708f8fSGustavo F. Padovan 	}
15980a708f8fSGustavo F. Padovan }
15990a708f8fSGustavo F. Padovan 
16005e4e3972SAndrei Emeltchenko static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
16010a708f8fSGustavo F. Padovan {
16025e4e3972SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
16030a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req req;
16040a708f8fSGustavo F. Padovan 
16050a708f8fSGustavo F. Padovan 	if (!conn)
16060a708f8fSGustavo F. Padovan 		return;
16070a708f8fSGustavo F. Padovan 
1608aad3d0e3SAndrei Emeltchenko 	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
16091a09bcb9SGustavo F. Padovan 		__clear_retrans_timer(chan);
16101a09bcb9SGustavo F. Padovan 		__clear_monitor_timer(chan);
16111a09bcb9SGustavo F. Padovan 		__clear_ack_timer(chan);
16120a708f8fSGustavo F. Padovan 	}
16130a708f8fSGustavo F. Padovan 
16142338a7e0SJohan Hedberg 	if (chan->scid == L2CAP_CID_A2MP) {
1615d117773cSGustavo Padovan 		l2cap_state_change(chan, BT_DISCONN);
1616416fa752SAndrei Emeltchenko 		return;
1617416fa752SAndrei Emeltchenko 	}
1618416fa752SAndrei Emeltchenko 
1619fe4128e0SGustavo F. Padovan 	req.dcid = cpu_to_le16(chan->dcid);
1620fe4128e0SGustavo F. Padovan 	req.scid = cpu_to_le16(chan->scid);
16212d792818SGustavo Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
16222d792818SGustavo Padovan 		       sizeof(req), &req);
16230a708f8fSGustavo F. Padovan 
1624f8e73017SGustavo Padovan 	l2cap_state_change_and_error(chan, BT_DISCONN, err);
16250a708f8fSGustavo F. Padovan }
16260a708f8fSGustavo F. Padovan 
16270a708f8fSGustavo F. Padovan /* ---- L2CAP connections ---- */
16280a708f8fSGustavo F. Padovan static void l2cap_conn_start(struct l2cap_conn *conn)
16290a708f8fSGustavo F. Padovan {
16303df91ea2SAndrei Emeltchenko 	struct l2cap_chan *chan, *tmp;
16310a708f8fSGustavo F. Padovan 
16320a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
16330a708f8fSGustavo F. Padovan 
16343df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
16350a708f8fSGustavo F. Padovan 
16363df91ea2SAndrei Emeltchenko 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
16376be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
16380a708f8fSGustavo F. Padovan 
1639715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1640aeaeb4bbSJohan Hedberg 			l2cap_chan_ready(chan);
16416be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
16420a708f8fSGustavo F. Padovan 			continue;
16430a708f8fSGustavo F. Padovan 		}
16440a708f8fSGustavo F. Padovan 
164589bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
1646e7cafc45SJohan Hedberg 			if (!l2cap_chan_check_security(chan, true) ||
1647b4450035SGustavo F. Padovan 			    !__l2cap_no_conn_pending(chan)) {
16486be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16490a708f8fSGustavo F. Padovan 				continue;
16500a708f8fSGustavo F. Padovan 			}
16510a708f8fSGustavo F. Padovan 
1652c1360a1cSGustavo F. Padovan 			if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
1653c1360a1cSGustavo F. Padovan 			    && test_bit(CONF_STATE2_DEVICE,
1654c1360a1cSGustavo F. Padovan 					&chan->conf_state)) {
16550f852724SGustavo F. Padovan 				l2cap_chan_close(chan, ECONNRESET);
16566be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16570a708f8fSGustavo F. Padovan 				continue;
16580a708f8fSGustavo F. Padovan 			}
16590a708f8fSGustavo F. Padovan 
1660693cd8ceSMarcel Holtmann 			if (l2cap_check_enc_key_size(conn->hcon))
166193c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
1662693cd8ceSMarcel Holtmann 			else
1663693cd8ceSMarcel Holtmann 				l2cap_chan_close(chan, ECONNREFUSED);
16640a708f8fSGustavo F. Padovan 
166589bc500eSGustavo F. Padovan 		} else if (chan->state == BT_CONNECT2) {
16660a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
16670a708f8fSGustavo F. Padovan 			char buf[128];
1668fe4128e0SGustavo F. Padovan 			rsp.scid = cpu_to_le16(chan->dcid);
1669fe4128e0SGustavo F. Padovan 			rsp.dcid = cpu_to_le16(chan->scid);
16700a708f8fSGustavo F. Padovan 
1671e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, false)) {
1672bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
1673dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1674dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
16752dc4e510SGustavo Padovan 					chan->ops->defer(chan);
16760a708f8fSGustavo F. Padovan 
16770a708f8fSGustavo F. Padovan 				} else {
1678acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
1679dcf4adbfSJoe Perches 					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1680dcf4adbfSJoe Perches 					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
16810a708f8fSGustavo F. Padovan 				}
16820a708f8fSGustavo F. Padovan 			} else {
1683dcf4adbfSJoe Perches 				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
1684dcf4adbfSJoe Perches 				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
16850a708f8fSGustavo F. Padovan 			}
16860a708f8fSGustavo F. Padovan 
1687fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
1688fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
16890a708f8fSGustavo F. Padovan 
1690c1360a1cSGustavo F. Padovan 			if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
16910a708f8fSGustavo F. Padovan 			    rsp.result != L2CAP_CR_SUCCESS) {
16926be36555SAndrei Emeltchenko 				l2cap_chan_unlock(chan);
16930a708f8fSGustavo F. Padovan 				continue;
16940a708f8fSGustavo F. Padovan 			}
16950a708f8fSGustavo F. Padovan 
1696c1360a1cSGustavo F. Padovan 			set_bit(CONF_REQ_SENT, &chan->conf_state);
16970a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1698e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
169973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
17000a708f8fSGustavo F. Padovan 		}
17010a708f8fSGustavo F. Padovan 
17026be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17030a708f8fSGustavo F. Padovan 	}
17040a708f8fSGustavo F. Padovan 
17053df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17060a708f8fSGustavo F. Padovan }
17070a708f8fSGustavo F. Padovan 
1708b62f328bSVille Tervo static void l2cap_le_conn_ready(struct l2cap_conn *conn)
1709b62f328bSVille Tervo {
1710cc8dba2bSMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
1711dcc36c16SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
1712b62f328bSVille Tervo 
1713e760ec12SJohan Hedberg 	BT_DBG("%s conn %p", hdev->name, conn);
1714b62f328bSVille Tervo 
1715e760ec12SJohan Hedberg 	/* For outgoing pairing which doesn't necessarily have an
1716e760ec12SJohan Hedberg 	 * associated socket (e.g. mgmt_pair_device).
1717e760ec12SJohan Hedberg 	 */
1718e760ec12SJohan Hedberg 	if (hcon->out)
1719e760ec12SJohan Hedberg 		smp_conn_security(hcon, hcon->pending_sec_level);
1720cc8dba2bSMarcel Holtmann 
172174be523cSArchie Pusaka 	/* For LE peripheral connections, make sure the connection interval
17225153ceb9SBhaskar Chowdhury 	 * is in the range of the minimum and maximum interval that has
172380afeb6cSMarcel Holtmann 	 * been configured for this connection. If not, then trigger
172480afeb6cSMarcel Holtmann 	 * the connection update procedure.
172580afeb6cSMarcel Holtmann 	 */
172640bef302SJohan Hedberg 	if (hcon->role == HCI_ROLE_SLAVE &&
172780afeb6cSMarcel Holtmann 	    (hcon->le_conn_interval < hcon->le_conn_min_interval ||
172880afeb6cSMarcel Holtmann 	     hcon->le_conn_interval > hcon->le_conn_max_interval)) {
172980afeb6cSMarcel Holtmann 		struct l2cap_conn_param_update_req req;
173080afeb6cSMarcel Holtmann 
173180afeb6cSMarcel Holtmann 		req.min = cpu_to_le16(hcon->le_conn_min_interval);
173280afeb6cSMarcel Holtmann 		req.max = cpu_to_le16(hcon->le_conn_max_interval);
173380afeb6cSMarcel Holtmann 		req.latency = cpu_to_le16(hcon->le_conn_latency);
173480afeb6cSMarcel Holtmann 		req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout);
173580afeb6cSMarcel Holtmann 
173680afeb6cSMarcel Holtmann 		l2cap_send_cmd(conn, l2cap_get_ident(conn),
173780afeb6cSMarcel Holtmann 			       L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req);
173880afeb6cSMarcel Holtmann 	}
1739b62f328bSVille Tervo }
1740b62f328bSVille Tervo 
17410a708f8fSGustavo F. Padovan static void l2cap_conn_ready(struct l2cap_conn *conn)
17420a708f8fSGustavo F. Padovan {
174348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
1744cc110922SVinicius Costa Gomes 	struct hci_conn *hcon = conn->hcon;
17450a708f8fSGustavo F. Padovan 
17460a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17470a708f8fSGustavo F. Padovan 
1748aeaeb4bbSJohan Hedberg 	if (hcon->type == ACL_LINK)
1749aeaeb4bbSJohan Hedberg 		l2cap_request_info(conn);
1750aeaeb4bbSJohan Hedberg 
1751e760ec12SJohan Hedberg 	mutex_lock(&conn->chan_lock);
1752e760ec12SJohan Hedberg 
17533df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1754baa7e1faSGustavo F. Padovan 
17556be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
17560a708f8fSGustavo F. Padovan 
17572338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
1758416fa752SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
1759416fa752SAndrei Emeltchenko 			continue;
1760416fa752SAndrei Emeltchenko 		}
1761416fa752SAndrei Emeltchenko 
1762cc110922SVinicius Costa Gomes 		if (hcon->type == LE_LINK) {
1763f1496deeSJohan Hedberg 			l2cap_le_start(chan);
176463128451SVinicius Costa Gomes 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
1765aeaeb4bbSJohan Hedberg 			if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
176674e75740SGustavo Padovan 				l2cap_chan_ready(chan);
17671c244f79SGustavo Padovan 		} else if (chan->state == BT_CONNECT) {
1768fc7f8a7eSGustavo F. Padovan 			l2cap_do_start(chan);
17691c244f79SGustavo Padovan 		}
17700a708f8fSGustavo F. Padovan 
17716be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
17720a708f8fSGustavo F. Padovan 	}
17730a708f8fSGustavo F. Padovan 
17743df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
177561a939c6SJohan Hedberg 
177679a05727SJohan Hedberg 	if (hcon->type == LE_LINK)
177779a05727SJohan Hedberg 		l2cap_le_conn_ready(conn);
177879a05727SJohan Hedberg 
177961a939c6SJohan Hedberg 	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
17800a708f8fSGustavo F. Padovan }
17810a708f8fSGustavo F. Padovan 
17820a708f8fSGustavo F. Padovan /* Notify sockets that we cannot guaranty reliability anymore */
17830a708f8fSGustavo F. Padovan static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
17840a708f8fSGustavo F. Padovan {
178548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
17860a708f8fSGustavo F. Padovan 
17870a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
17880a708f8fSGustavo F. Padovan 
17893df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
17900a708f8fSGustavo F. Padovan 
17913df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
1792ecf61bdbSAndrei Emeltchenko 		if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
17931d8b1fd5SGustavo Padovan 			l2cap_chan_set_err(chan, err);
17940a708f8fSGustavo F. Padovan 	}
17950a708f8fSGustavo F. Padovan 
17963df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
17970a708f8fSGustavo F. Padovan }
17980a708f8fSGustavo F. Padovan 
1799f878fcadSGustavo F. Padovan static void l2cap_info_timeout(struct work_struct *work)
18000a708f8fSGustavo F. Padovan {
1801f878fcadSGustavo F. Padovan 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
1802030013d8SGustavo F. Padovan 					       info_timer.work);
18030a708f8fSGustavo F. Padovan 
18040a708f8fSGustavo F. Padovan 	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
18050a708f8fSGustavo F. Padovan 	conn->info_ident = 0;
18060a708f8fSGustavo F. Padovan 
18070a708f8fSGustavo F. Padovan 	l2cap_conn_start(conn);
18080a708f8fSGustavo F. Padovan }
18090a708f8fSGustavo F. Padovan 
18102c8e1411SDavid Herrmann /*
18112c8e1411SDavid Herrmann  * l2cap_user
18122c8e1411SDavid Herrmann  * External modules can register l2cap_user objects on l2cap_conn. The ->probe
18132c8e1411SDavid Herrmann  * callback is called during registration. The ->remove callback is called
18142c8e1411SDavid Herrmann  * during unregistration.
18152c8e1411SDavid Herrmann  * An l2cap_user object can either be explicitly unregistered or when the
18162c8e1411SDavid Herrmann  * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
18172c8e1411SDavid Herrmann  * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
18182c8e1411SDavid Herrmann  * External modules must own a reference to the l2cap_conn object if they intend
18192c8e1411SDavid Herrmann  * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
18202c8e1411SDavid Herrmann  * any time if they don't.
18212c8e1411SDavid Herrmann  */
18222c8e1411SDavid Herrmann 
18232c8e1411SDavid Herrmann int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
18242c8e1411SDavid Herrmann {
18252c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
18262c8e1411SDavid Herrmann 	int ret;
18272c8e1411SDavid Herrmann 
18282c8e1411SDavid Herrmann 	/* We need to check whether l2cap_conn is registered. If it is not, we
18292c8e1411SDavid Herrmann 	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
18302c8e1411SDavid Herrmann 	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
18312c8e1411SDavid Herrmann 	 * relies on the parent hci_conn object to be locked. This itself relies
18322c8e1411SDavid Herrmann 	 * on the hci_dev object to be locked. So we must lock the hci device
18332c8e1411SDavid Herrmann 	 * here, too. */
18342c8e1411SDavid Herrmann 
18352c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18362c8e1411SDavid Herrmann 
1837835a6a2fSAlexey Dobriyan 	if (!list_empty(&user->list)) {
18382c8e1411SDavid Herrmann 		ret = -EINVAL;
18392c8e1411SDavid Herrmann 		goto out_unlock;
18402c8e1411SDavid Herrmann 	}
18412c8e1411SDavid Herrmann 
18422c8e1411SDavid Herrmann 	/* conn->hchan is NULL after l2cap_conn_del() was called */
18432c8e1411SDavid Herrmann 	if (!conn->hchan) {
18442c8e1411SDavid Herrmann 		ret = -ENODEV;
18452c8e1411SDavid Herrmann 		goto out_unlock;
18462c8e1411SDavid Herrmann 	}
18472c8e1411SDavid Herrmann 
18482c8e1411SDavid Herrmann 	ret = user->probe(conn, user);
18492c8e1411SDavid Herrmann 	if (ret)
18502c8e1411SDavid Herrmann 		goto out_unlock;
18512c8e1411SDavid Herrmann 
18522c8e1411SDavid Herrmann 	list_add(&user->list, &conn->users);
18532c8e1411SDavid Herrmann 	ret = 0;
18542c8e1411SDavid Herrmann 
18552c8e1411SDavid Herrmann out_unlock:
18562c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18572c8e1411SDavid Herrmann 	return ret;
18582c8e1411SDavid Herrmann }
18592c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_register_user);
18602c8e1411SDavid Herrmann 
18612c8e1411SDavid Herrmann void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
18622c8e1411SDavid Herrmann {
18632c8e1411SDavid Herrmann 	struct hci_dev *hdev = conn->hcon->hdev;
18642c8e1411SDavid Herrmann 
18652c8e1411SDavid Herrmann 	hci_dev_lock(hdev);
18662c8e1411SDavid Herrmann 
1867835a6a2fSAlexey Dobriyan 	if (list_empty(&user->list))
18682c8e1411SDavid Herrmann 		goto out_unlock;
18692c8e1411SDavid Herrmann 
1870ab944c83STedd Ho-Jeong An 	list_del_init(&user->list);
18712c8e1411SDavid Herrmann 	user->remove(conn, user);
18722c8e1411SDavid Herrmann 
18732c8e1411SDavid Herrmann out_unlock:
18742c8e1411SDavid Herrmann 	hci_dev_unlock(hdev);
18752c8e1411SDavid Herrmann }
18762c8e1411SDavid Herrmann EXPORT_SYMBOL(l2cap_unregister_user);
18772c8e1411SDavid Herrmann 
18782c8e1411SDavid Herrmann static void l2cap_unregister_all_users(struct l2cap_conn *conn)
18792c8e1411SDavid Herrmann {
18802c8e1411SDavid Herrmann 	struct l2cap_user *user;
18812c8e1411SDavid Herrmann 
18822c8e1411SDavid Herrmann 	while (!list_empty(&conn->users)) {
18832c8e1411SDavid Herrmann 		user = list_first_entry(&conn->users, struct l2cap_user, list);
1884ab944c83STedd Ho-Jeong An 		list_del_init(&user->list);
18852c8e1411SDavid Herrmann 		user->remove(conn, user);
18862c8e1411SDavid Herrmann 	}
18872c8e1411SDavid Herrmann }
18882c8e1411SDavid Herrmann 
18895d3de7dfSVinicius Costa Gomes static void l2cap_conn_del(struct hci_conn *hcon, int err)
18905d3de7dfSVinicius Costa Gomes {
18915d3de7dfSVinicius Costa Gomes 	struct l2cap_conn *conn = hcon->l2cap_data;
18925d3de7dfSVinicius Costa Gomes 	struct l2cap_chan *chan, *l;
18935d3de7dfSVinicius Costa Gomes 
18945d3de7dfSVinicius Costa Gomes 	if (!conn)
18955d3de7dfSVinicius Costa Gomes 		return;
18965d3de7dfSVinicius Costa Gomes 
18975d3de7dfSVinicius Costa Gomes 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
18985d3de7dfSVinicius Costa Gomes 
18995d3de7dfSVinicius Costa Gomes 	kfree_skb(conn->rx_skb);
19005d3de7dfSVinicius Costa Gomes 
190161a939c6SJohan Hedberg 	skb_queue_purge(&conn->pending_rx);
19027ab56c3aSJukka Taimisto 
19037ab56c3aSJukka Taimisto 	/* We can not call flush_work(&conn->pending_rx_work) here since we
19047ab56c3aSJukka Taimisto 	 * might block if we are running on a worker from the same workqueue
19057ab56c3aSJukka Taimisto 	 * pending_rx_work is waiting on.
19067ab56c3aSJukka Taimisto 	 */
19077ab56c3aSJukka Taimisto 	if (work_pending(&conn->pending_rx_work))
19087ab56c3aSJukka Taimisto 		cancel_work_sync(&conn->pending_rx_work);
190961a939c6SJohan Hedberg 
1910f3d82d0cSJohan Hedberg 	if (work_pending(&conn->id_addr_update_work))
1911f3d82d0cSJohan Hedberg 		cancel_work_sync(&conn->id_addr_update_work);
1912f3d82d0cSJohan Hedberg 
19132c8e1411SDavid Herrmann 	l2cap_unregister_all_users(conn);
19142c8e1411SDavid Herrmann 
1915e31fb860SJohan Hedberg 	/* Force the connection to be immediately dropped */
1916e31fb860SJohan Hedberg 	hcon->disc_timeout = 0;
1917e31fb860SJohan Hedberg 
19183df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
19193df91ea2SAndrei Emeltchenko 
19205d3de7dfSVinicius Costa Gomes 	/* Kill channels */
19215d3de7dfSVinicius Costa Gomes 	list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
192261d6ef3eSMat Martineau 		l2cap_chan_hold(chan);
19236be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
19246be36555SAndrei Emeltchenko 
19255d3de7dfSVinicius Costa Gomes 		l2cap_chan_del(chan, err);
19266be36555SAndrei Emeltchenko 
192780b98027SGustavo Padovan 		chan->ops->close(chan);
19286c08fc89SManish Mandlik 
19296c08fc89SManish Mandlik 		l2cap_chan_unlock(chan);
193061d6ef3eSMat Martineau 		l2cap_chan_put(chan);
19315d3de7dfSVinicius Costa Gomes 	}
19325d3de7dfSVinicius Costa Gomes 
19333df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
19343df91ea2SAndrei Emeltchenko 
193573d80debSLuiz Augusto von Dentz 	hci_chan_del(conn->hchan);
193673d80debSLuiz Augusto von Dentz 
19375d3de7dfSVinicius Costa Gomes 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
1938127074bfSUlisses Furquim 		cancel_delayed_work_sync(&conn->info_timer);
19395d3de7dfSVinicius Costa Gomes 
19405d3de7dfSVinicius Costa Gomes 	hcon->l2cap_data = NULL;
19419c903e37SDavid Herrmann 	conn->hchan = NULL;
19429c903e37SDavid Herrmann 	l2cap_conn_put(conn);
19435d3de7dfSVinicius Costa Gomes }
19445d3de7dfSVinicius Costa Gomes 
19459c903e37SDavid Herrmann static void l2cap_conn_free(struct kref *ref)
19469c903e37SDavid Herrmann {
19479c903e37SDavid Herrmann 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
19489c903e37SDavid Herrmann 
19499c903e37SDavid Herrmann 	hci_conn_put(conn->hcon);
19509c903e37SDavid Herrmann 	kfree(conn);
19519c903e37SDavid Herrmann }
19529c903e37SDavid Herrmann 
195351bb8457SJohan Hedberg struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn)
19549c903e37SDavid Herrmann {
19559c903e37SDavid Herrmann 	kref_get(&conn->ref);
195651bb8457SJohan Hedberg 	return conn;
19579c903e37SDavid Herrmann }
19589c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_get);
19599c903e37SDavid Herrmann 
19609c903e37SDavid Herrmann void l2cap_conn_put(struct l2cap_conn *conn)
19619c903e37SDavid Herrmann {
19629c903e37SDavid Herrmann 	kref_put(&conn->ref, l2cap_conn_free);
19639c903e37SDavid Herrmann }
19649c903e37SDavid Herrmann EXPORT_SYMBOL(l2cap_conn_put);
19659c903e37SDavid Herrmann 
19660a708f8fSGustavo F. Padovan /* ---- Socket interface ---- */
19670a708f8fSGustavo F. Padovan 
1968c2287681SIdo Yariv /* Find socket with psm and source / destination bdaddr.
19690a708f8fSGustavo F. Padovan  * Returns closest match.
19700a708f8fSGustavo F. Padovan  */
1971c2287681SIdo Yariv static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
1972c2287681SIdo Yariv 						   bdaddr_t *src,
1973bf20fd4eSJohan Hedberg 						   bdaddr_t *dst,
1974bf20fd4eSJohan Hedberg 						   u8 link_type)
19750a708f8fSGustavo F. Padovan {
1976332f1795SLuiz Augusto von Dentz 	struct l2cap_chan *c, *tmp, *c1 = NULL;
19770a708f8fSGustavo F. Padovan 
197823691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
19790a708f8fSGustavo F. Padovan 
1980332f1795SLuiz Augusto von Dentz 	list_for_each_entry_safe(c, tmp, &chan_list, global_l) {
198189bc500eSGustavo F. Padovan 		if (state && c->state != state)
19820a708f8fSGustavo F. Padovan 			continue;
19830a708f8fSGustavo F. Padovan 
1984bf20fd4eSJohan Hedberg 		if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
1985bf20fd4eSJohan Hedberg 			continue;
1986bf20fd4eSJohan Hedberg 
1987bf20fd4eSJohan Hedberg 		if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
1988bf20fd4eSJohan Hedberg 			continue;
1989bf20fd4eSJohan Hedberg 
1990f937b758SLuiz Augusto von Dentz 		if (c->chan_type != L2CAP_CHAN_FIXED && c->psm == psm) {
1991c2287681SIdo Yariv 			int src_match, dst_match;
1992c2287681SIdo Yariv 			int src_any, dst_any;
1993c2287681SIdo Yariv 
19940a708f8fSGustavo F. Padovan 			/* Exact match. */
19957eafc59eSMarcel Holtmann 			src_match = !bacmp(&c->src, src);
19967eafc59eSMarcel Holtmann 			dst_match = !bacmp(&c->dst, dst);
1997c2287681SIdo Yariv 			if (src_match && dst_match) {
1998fc5ae5b4SLuiz Augusto von Dentz 				if (!l2cap_chan_hold_unless_zero(c))
1999fc5ae5b4SLuiz Augusto von Dentz 					continue;
2000fc5ae5b4SLuiz Augusto von Dentz 
2001a7567b20SJohannes Berg 				read_unlock(&chan_list_lock);
200223691d75SGustavo F. Padovan 				return c;
200323691d75SGustavo F. Padovan 			}
20040a708f8fSGustavo F. Padovan 
20050a708f8fSGustavo F. Padovan 			/* Closest match */
20067eafc59eSMarcel Holtmann 			src_any = !bacmp(&c->src, BDADDR_ANY);
20077eafc59eSMarcel Holtmann 			dst_any = !bacmp(&c->dst, BDADDR_ANY);
2008c2287681SIdo Yariv 			if ((src_match && dst_any) || (src_any && dst_match) ||
2009c2287681SIdo Yariv 			    (src_any && dst_any))
201023691d75SGustavo F. Padovan 				c1 = c;
20110a708f8fSGustavo F. Padovan 		}
20120a708f8fSGustavo F. Padovan 	}
20130a708f8fSGustavo F. Padovan 
2014a24cce14SJohan Hedberg 	if (c1)
2015d0be8347SLuiz Augusto von Dentz 		c1 = l2cap_chan_hold_unless_zero(c1);
2016a24cce14SJohan Hedberg 
201723691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
20180a708f8fSGustavo F. Padovan 
201923691d75SGustavo F. Padovan 	return c1;
20200a708f8fSGustavo F. Padovan }
20210a708f8fSGustavo F. Padovan 
2022721c4181SGustavo F. Padovan static void l2cap_monitor_timeout(struct work_struct *work)
20230a708f8fSGustavo F. Padovan {
2024721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2025721c4181SGustavo F. Padovan 					       monitor_timer.work);
20260a708f8fSGustavo F. Padovan 
2027525cd185SGustavo F. Padovan 	BT_DBG("chan %p", chan);
20280a708f8fSGustavo F. Padovan 
20296be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20306be36555SAndrei Emeltchenko 
203180909e04SMat Martineau 	if (!chan->conn) {
20326be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
20338d7e1c7fSAndrei Emeltchenko 		l2cap_chan_put(chan);
20340a708f8fSGustavo F. Padovan 		return;
20350a708f8fSGustavo F. Padovan 	}
20360a708f8fSGustavo F. Padovan 
2037401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_MONITOR_TO);
20380a708f8fSGustavo F. Padovan 
20396be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20408d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20410a708f8fSGustavo F. Padovan }
20420a708f8fSGustavo F. Padovan 
2043721c4181SGustavo F. Padovan static void l2cap_retrans_timeout(struct work_struct *work)
20440a708f8fSGustavo F. Padovan {
2045721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
2046721c4181SGustavo F. Padovan 					       retrans_timer.work);
20470a708f8fSGustavo F. Padovan 
204849208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
20490a708f8fSGustavo F. Padovan 
20506be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
20516be36555SAndrei Emeltchenko 
205280909e04SMat Martineau 	if (!chan->conn) {
205380909e04SMat Martineau 		l2cap_chan_unlock(chan);
205480909e04SMat Martineau 		l2cap_chan_put(chan);
205580909e04SMat Martineau 		return;
205680909e04SMat Martineau 	}
20570a708f8fSGustavo F. Padovan 
2058401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, L2CAP_EV_RETRANS_TO);
20596be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
20608d7e1c7fSAndrei Emeltchenko 	l2cap_chan_put(chan);
20610a708f8fSGustavo F. Padovan }
20620a708f8fSGustavo F. Padovan 
2063d660366dSGustavo Padovan static void l2cap_streaming_send(struct l2cap_chan *chan,
20643733937dSMat Martineau 				 struct sk_buff_head *skbs)
20650a708f8fSGustavo F. Padovan {
20660a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
20673733937dSMat Martineau 	struct l2cap_ctrl *control;
20680a708f8fSGustavo F. Padovan 
20693733937dSMat Martineau 	BT_DBG("chan %p, skbs %p", chan, skbs);
20703733937dSMat Martineau 
2071b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2072b99e13adSMat Martineau 		return;
2073b99e13adSMat Martineau 
20743733937dSMat Martineau 	skb_queue_splice_tail_init(skbs, &chan->tx_q);
20753733937dSMat Martineau 
20763733937dSMat Martineau 	while (!skb_queue_empty(&chan->tx_q)) {
20773733937dSMat Martineau 
20783733937dSMat Martineau 		skb = skb_dequeue(&chan->tx_q);
20793733937dSMat Martineau 
2080a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2081a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
20823733937dSMat Martineau 
20833733937dSMat Martineau 		control->reqseq = 0;
20843733937dSMat Martineau 		control->txseq = chan->next_tx_seq;
20853733937dSMat Martineau 
20863733937dSMat Martineau 		__pack_control(chan, control, skb);
20870a708f8fSGustavo F. Padovan 
208847d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
20893733937dSMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
20903733937dSMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
20910a708f8fSGustavo F. Padovan 		}
20920a708f8fSGustavo F. Padovan 
20934343478fSGustavo F. Padovan 		l2cap_do_send(chan, skb);
20940a708f8fSGustavo F. Padovan 
2095b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
20963733937dSMat Martineau 
2097836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
20983733937dSMat Martineau 		chan->frames_sent++;
20990a708f8fSGustavo F. Padovan 	}
21000a708f8fSGustavo F. Padovan }
21010a708f8fSGustavo F. Padovan 
210267c9e840SSzymon Janc static int l2cap_ertm_send(struct l2cap_chan *chan)
21030a708f8fSGustavo F. Padovan {
21040a708f8fSGustavo F. Padovan 	struct sk_buff *skb, *tx_skb;
210518a48e76SMat Martineau 	struct l2cap_ctrl *control;
210618a48e76SMat Martineau 	int sent = 0;
210718a48e76SMat Martineau 
210818a48e76SMat Martineau 	BT_DBG("chan %p", chan);
21090a708f8fSGustavo F. Padovan 
211089bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
21110a708f8fSGustavo F. Padovan 		return -ENOTCONN;
21120a708f8fSGustavo F. Padovan 
211394122bbeSMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
211494122bbeSMat Martineau 		return 0;
211594122bbeSMat Martineau 
2116b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2117b99e13adSMat Martineau 		return 0;
2118b99e13adSMat Martineau 
211918a48e76SMat Martineau 	while (chan->tx_send_head &&
212018a48e76SMat Martineau 	       chan->unacked_frames < chan->remote_tx_win &&
212118a48e76SMat Martineau 	       chan->tx_state == L2CAP_TX_STATE_XMIT) {
21220a708f8fSGustavo F. Padovan 
212318a48e76SMat Martineau 		skb = chan->tx_send_head;
21240a708f8fSGustavo F. Padovan 
2125a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries = 1;
2126a4368ff3SJohan Hedberg 		control = &bt_cb(skb)->l2cap;
21270a708f8fSGustavo F. Padovan 
2128e2ab4353SGustavo F. Padovan 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
212918a48e76SMat Martineau 			control->final = 1;
2130e2ab4353SGustavo F. Padovan 
213118a48e76SMat Martineau 		control->reqseq = chan->buffer_seq;
213218a48e76SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
213318a48e76SMat Martineau 		control->txseq = chan->next_tx_seq;
21340a708f8fSGustavo F. Padovan 
213518a48e76SMat Martineau 		__pack_control(chan, control, skb);
21360a708f8fSGustavo F. Padovan 
213747d1ec61SGustavo F. Padovan 		if (chan->fcs == L2CAP_FCS_CRC16) {
213818a48e76SMat Martineau 			u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
213918a48e76SMat Martineau 			put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
21400a708f8fSGustavo F. Padovan 		}
21410a708f8fSGustavo F. Padovan 
214218a48e76SMat Martineau 		/* Clone after data has been modified. Data is assumed to be
214318a48e76SMat Martineau 		   read-only (for locking purposes) on cloned sk_buffs.
214418a48e76SMat Martineau 		 */
214518a48e76SMat Martineau 		tx_skb = skb_clone(skb, GFP_KERNEL);
214618a48e76SMat Martineau 
214718a48e76SMat Martineau 		if (!tx_skb)
214818a48e76SMat Martineau 			break;
21490a708f8fSGustavo F. Padovan 
21501a09bcb9SGustavo F. Padovan 		__set_retrans_timer(chan);
21510a708f8fSGustavo F. Padovan 
2152836be934SAndrei Emeltchenko 		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
21536a026610SGustavo F. Padovan 		chan->unacked_frames++;
21546a026610SGustavo F. Padovan 		chan->frames_sent++;
215518a48e76SMat Martineau 		sent++;
21560a708f8fSGustavo F. Padovan 
215758d35f87SGustavo F. Padovan 		if (skb_queue_is_last(&chan->tx_q, skb))
215858d35f87SGustavo F. Padovan 			chan->tx_send_head = NULL;
21590a708f8fSGustavo F. Padovan 		else
216058d35f87SGustavo F. Padovan 			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);
216118a48e76SMat Martineau 
216218a48e76SMat Martineau 		l2cap_do_send(chan, tx_skb);
2163b4400672SAndrei Emeltchenko 		BT_DBG("Sent txseq %u", control->txseq);
21640a708f8fSGustavo F. Padovan 	}
21650a708f8fSGustavo F. Padovan 
2166b4400672SAndrei Emeltchenko 	BT_DBG("Sent %d, %u unacked, %u in ERTM queue", sent,
2167b4400672SAndrei Emeltchenko 	       chan->unacked_frames, skb_queue_len(&chan->tx_q));
216818a48e76SMat Martineau 
216918a48e76SMat Martineau 	return sent;
21700a708f8fSGustavo F. Padovan }
21710a708f8fSGustavo F. Padovan 
2172e1fbd4c1SMat Martineau static void l2cap_ertm_resend(struct l2cap_chan *chan)
2173e1fbd4c1SMat Martineau {
2174e1fbd4c1SMat Martineau 	struct l2cap_ctrl control;
2175e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2176e1fbd4c1SMat Martineau 	struct sk_buff *tx_skb;
2177e1fbd4c1SMat Martineau 	u16 seq;
2178e1fbd4c1SMat Martineau 
2179e1fbd4c1SMat Martineau 	BT_DBG("chan %p", chan);
2180e1fbd4c1SMat Martineau 
2181e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2182e1fbd4c1SMat Martineau 		return;
2183e1fbd4c1SMat Martineau 
2184b99e13adSMat Martineau 	if (__chan_is_moving(chan))
2185b99e13adSMat Martineau 		return;
2186b99e13adSMat Martineau 
2187e1fbd4c1SMat Martineau 	while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
2188e1fbd4c1SMat Martineau 		seq = l2cap_seq_list_pop(&chan->retrans_list);
2189e1fbd4c1SMat Martineau 
2190e1fbd4c1SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq);
2191e1fbd4c1SMat Martineau 		if (!skb) {
2192e1fbd4c1SMat Martineau 			BT_DBG("Error: Can't retransmit seq %d, frame missing",
2193e1fbd4c1SMat Martineau 			       seq);
2194e1fbd4c1SMat Martineau 			continue;
2195e1fbd4c1SMat Martineau 		}
2196e1fbd4c1SMat Martineau 
2197a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.retries++;
2198a4368ff3SJohan Hedberg 		control = bt_cb(skb)->l2cap;
2199e1fbd4c1SMat Martineau 
2200e1fbd4c1SMat Martineau 		if (chan->max_tx != 0 &&
2201a4368ff3SJohan Hedberg 		    bt_cb(skb)->l2cap.retries > chan->max_tx) {
2202e1fbd4c1SMat Martineau 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
22035e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
2204e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2205e1fbd4c1SMat Martineau 			break;
2206e1fbd4c1SMat Martineau 		}
2207e1fbd4c1SMat Martineau 
2208e1fbd4c1SMat Martineau 		control.reqseq = chan->buffer_seq;
2209e1fbd4c1SMat Martineau 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
2210e1fbd4c1SMat Martineau 			control.final = 1;
2211e1fbd4c1SMat Martineau 		else
2212e1fbd4c1SMat Martineau 			control.final = 0;
2213e1fbd4c1SMat Martineau 
2214e1fbd4c1SMat Martineau 		if (skb_cloned(skb)) {
2215e1fbd4c1SMat Martineau 			/* Cloned sk_buffs are read-only, so we need a
2216e1fbd4c1SMat Martineau 			 * writeable copy
2217e1fbd4c1SMat Martineau 			 */
22188bcde1f2SGustavo Padovan 			tx_skb = skb_copy(skb, GFP_KERNEL);
2219e1fbd4c1SMat Martineau 		} else {
22208bcde1f2SGustavo Padovan 			tx_skb = skb_clone(skb, GFP_KERNEL);
2221e1fbd4c1SMat Martineau 		}
2222e1fbd4c1SMat Martineau 
2223e1fbd4c1SMat Martineau 		if (!tx_skb) {
2224e1fbd4c1SMat Martineau 			l2cap_seq_list_clear(&chan->retrans_list);
2225e1fbd4c1SMat Martineau 			break;
2226e1fbd4c1SMat Martineau 		}
2227e1fbd4c1SMat Martineau 
2228e1fbd4c1SMat Martineau 		/* Update skb contents */
2229e1fbd4c1SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
2230e1fbd4c1SMat Martineau 			put_unaligned_le32(__pack_extended_control(&control),
2231e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2232e1fbd4c1SMat Martineau 		} else {
2233e1fbd4c1SMat Martineau 			put_unaligned_le16(__pack_enhanced_control(&control),
2234e1fbd4c1SMat Martineau 					   tx_skb->data + L2CAP_HDR_SIZE);
2235e1fbd4c1SMat Martineau 		}
2236e1fbd4c1SMat Martineau 
223713cac152SLukasz Rymanowski 		/* Update FCS */
2238e1fbd4c1SMat Martineau 		if (chan->fcs == L2CAP_FCS_CRC16) {
223913cac152SLukasz Rymanowski 			u16 fcs = crc16(0, (u8 *) tx_skb->data,
224013cac152SLukasz Rymanowski 					tx_skb->len - L2CAP_FCS_SIZE);
224113cac152SLukasz Rymanowski 			put_unaligned_le16(fcs, skb_tail_pointer(tx_skb) -
224213cac152SLukasz Rymanowski 						L2CAP_FCS_SIZE);
2243e1fbd4c1SMat Martineau 		}
2244e1fbd4c1SMat Martineau 
2245e1fbd4c1SMat Martineau 		l2cap_do_send(chan, tx_skb);
2246e1fbd4c1SMat Martineau 
2247e1fbd4c1SMat Martineau 		BT_DBG("Resent txseq %d", control.txseq);
2248e1fbd4c1SMat Martineau 
2249e1fbd4c1SMat Martineau 		chan->last_acked_seq = chan->buffer_seq;
2250e1fbd4c1SMat Martineau 	}
2251e1fbd4c1SMat Martineau }
2252e1fbd4c1SMat Martineau 
2253f80842a8SMat Martineau static void l2cap_retransmit(struct l2cap_chan *chan,
2254f80842a8SMat Martineau 			     struct l2cap_ctrl *control)
2255f80842a8SMat Martineau {
2256f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2257f80842a8SMat Martineau 
2258f80842a8SMat Martineau 	l2cap_seq_list_append(&chan->retrans_list, control->reqseq);
2259f80842a8SMat Martineau 	l2cap_ertm_resend(chan);
2260f80842a8SMat Martineau }
2261f80842a8SMat Martineau 
2262d2a7ac5dSMat Martineau static void l2cap_retransmit_all(struct l2cap_chan *chan,
2263d2a7ac5dSMat Martineau 				 struct l2cap_ctrl *control)
2264d2a7ac5dSMat Martineau {
2265e1fbd4c1SMat Martineau 	struct sk_buff *skb;
2266e1fbd4c1SMat Martineau 
2267e1fbd4c1SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
2268e1fbd4c1SMat Martineau 
2269e1fbd4c1SMat Martineau 	if (control->poll)
2270e1fbd4c1SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
2271e1fbd4c1SMat Martineau 
2272e1fbd4c1SMat Martineau 	l2cap_seq_list_clear(&chan->retrans_list);
2273e1fbd4c1SMat Martineau 
2274e1fbd4c1SMat Martineau 	if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
2275e1fbd4c1SMat Martineau 		return;
2276e1fbd4c1SMat Martineau 
2277e1fbd4c1SMat Martineau 	if (chan->unacked_frames) {
2278e1fbd4c1SMat Martineau 		skb_queue_walk(&chan->tx_q, skb) {
2279a4368ff3SJohan Hedberg 			if (bt_cb(skb)->l2cap.txseq == control->reqseq ||
2280e1fbd4c1SMat Martineau 			    skb == chan->tx_send_head)
2281e1fbd4c1SMat Martineau 				break;
2282e1fbd4c1SMat Martineau 		}
2283e1fbd4c1SMat Martineau 
2284e1fbd4c1SMat Martineau 		skb_queue_walk_from(&chan->tx_q, skb) {
2285e1fbd4c1SMat Martineau 			if (skb == chan->tx_send_head)
2286e1fbd4c1SMat Martineau 				break;
2287e1fbd4c1SMat Martineau 
2288e1fbd4c1SMat Martineau 			l2cap_seq_list_append(&chan->retrans_list,
2289a4368ff3SJohan Hedberg 					      bt_cb(skb)->l2cap.txseq);
2290e1fbd4c1SMat Martineau 		}
2291e1fbd4c1SMat Martineau 
2292e1fbd4c1SMat Martineau 		l2cap_ertm_resend(chan);
2293e1fbd4c1SMat Martineau 	}
2294d2a7ac5dSMat Martineau }
2295d2a7ac5dSMat Martineau 
2296b17e73bbSSzymon Janc static void l2cap_send_ack(struct l2cap_chan *chan)
2297b17e73bbSSzymon Janc {
22980a0aba42SMat Martineau 	struct l2cap_ctrl control;
22990a0aba42SMat Martineau 	u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
23000a0aba42SMat Martineau 					 chan->last_acked_seq);
23010a0aba42SMat Martineau 	int threshold;
23020a0aba42SMat Martineau 
23030a0aba42SMat Martineau 	BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
23040a0aba42SMat Martineau 	       chan, chan->last_acked_seq, chan->buffer_seq);
23050a0aba42SMat Martineau 
23060a0aba42SMat Martineau 	memset(&control, 0, sizeof(control));
23070a0aba42SMat Martineau 	control.sframe = 1;
23080a0aba42SMat Martineau 
23090a0aba42SMat Martineau 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
23100a0aba42SMat Martineau 	    chan->rx_state == L2CAP_RX_STATE_RECV) {
2311b17e73bbSSzymon Janc 		__clear_ack_timer(chan);
23120a0aba42SMat Martineau 		control.super = L2CAP_SUPER_RNR;
23130a0aba42SMat Martineau 		control.reqseq = chan->buffer_seq;
23140a0aba42SMat Martineau 		l2cap_send_sframe(chan, &control);
23150a0aba42SMat Martineau 	} else {
23160a0aba42SMat Martineau 		if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
23170a0aba42SMat Martineau 			l2cap_ertm_send(chan);
23180a0aba42SMat Martineau 			/* If any i-frames were sent, they included an ack */
23190a0aba42SMat Martineau 			if (chan->buffer_seq == chan->last_acked_seq)
23200a0aba42SMat Martineau 				frames_to_ack = 0;
23210a0aba42SMat Martineau 		}
23220a0aba42SMat Martineau 
2323c20f8e35SMat Martineau 		/* Ack now if the window is 3/4ths full.
23240a0aba42SMat Martineau 		 * Calculate without mul or div
23250a0aba42SMat Martineau 		 */
2326c20f8e35SMat Martineau 		threshold = chan->ack_win;
23270a0aba42SMat Martineau 		threshold += threshold << 1;
23280a0aba42SMat Martineau 		threshold >>= 2;
23290a0aba42SMat Martineau 
2330b4400672SAndrei Emeltchenko 		BT_DBG("frames_to_ack %u, threshold %d", frames_to_ack,
23310a0aba42SMat Martineau 		       threshold);
23320a0aba42SMat Martineau 
23330a0aba42SMat Martineau 		if (frames_to_ack >= threshold) {
23340a0aba42SMat Martineau 			__clear_ack_timer(chan);
23350a0aba42SMat Martineau 			control.super = L2CAP_SUPER_RR;
23360a0aba42SMat Martineau 			control.reqseq = chan->buffer_seq;
23370a0aba42SMat Martineau 			l2cap_send_sframe(chan, &control);
23380a0aba42SMat Martineau 			frames_to_ack = 0;
23390a0aba42SMat Martineau 		}
23400a0aba42SMat Martineau 
23410a0aba42SMat Martineau 		if (frames_to_ack)
23420a0aba42SMat Martineau 			__set_ack_timer(chan);
23430a0aba42SMat Martineau 	}
2344b17e73bbSSzymon Janc }
2345b17e73bbSSzymon Janc 
234604124681SGustavo F. Padovan static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
234704124681SGustavo F. Padovan 					 struct msghdr *msg, int len,
234804124681SGustavo F. Padovan 					 int count, struct sk_buff *skb)
23490a708f8fSGustavo F. Padovan {
23500952a57aSAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
23510a708f8fSGustavo F. Padovan 	struct sk_buff **frag;
235290338947SGustavo Padovan 	int sent = 0;
23530a708f8fSGustavo F. Padovan 
2354cbbd26b8SAl Viro 	if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter))
23550a708f8fSGustavo F. Padovan 		return -EFAULT;
23560a708f8fSGustavo F. Padovan 
23570a708f8fSGustavo F. Padovan 	sent += count;
23580a708f8fSGustavo F. Padovan 	len  -= count;
23590a708f8fSGustavo F. Padovan 
23600a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
23610a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
23620a708f8fSGustavo F. Padovan 	while (len) {
2363fbe00700SGustavo Padovan 		struct sk_buff *tmp;
2364fbe00700SGustavo Padovan 
23650a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
23660a708f8fSGustavo F. Padovan 
2367d9fbd02bSMarcel Holtmann 		tmp = chan->ops->alloc_skb(chan, 0, count,
236890338947SGustavo Padovan 					   msg->msg_flags & MSG_DONTWAIT);
2369fbe00700SGustavo Padovan 		if (IS_ERR(tmp))
2370fbe00700SGustavo Padovan 			return PTR_ERR(tmp);
23712f7719ceSAndrei Emeltchenko 
2372fbe00700SGustavo Padovan 		*frag = tmp;
2373fbe00700SGustavo Padovan 
2374cbbd26b8SAl Viro 		if (!copy_from_iter_full(skb_put(*frag, count), count,
2375cbbd26b8SAl Viro 				   &msg->msg_iter))
23760a708f8fSGustavo F. Padovan 			return -EFAULT;
23770a708f8fSGustavo F. Padovan 
23780a708f8fSGustavo F. Padovan 		sent += count;
23790a708f8fSGustavo F. Padovan 		len  -= count;
23800a708f8fSGustavo F. Padovan 
23812d0ed3d5SGustavo Padovan 		skb->len += (*frag)->len;
23822d0ed3d5SGustavo Padovan 		skb->data_len += (*frag)->len;
23832d0ed3d5SGustavo Padovan 
23840a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
23850a708f8fSGustavo F. Padovan 	}
23860a708f8fSGustavo F. Padovan 
23870a708f8fSGustavo F. Padovan 	return sent;
23880a708f8fSGustavo F. Padovan }
23890a708f8fSGustavo F. Padovan 
23905e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
23918d46321cSMarcel Holtmann 						 struct msghdr *msg, size_t len)
23920a708f8fSGustavo F. Padovan {
23938c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
23940a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
239503a51213SAndrei Emeltchenko 	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
23960a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
23970a708f8fSGustavo F. Padovan 
23988d46321cSMarcel Holtmann 	BT_DBG("chan %p psm 0x%2.2x len %zu", chan,
23998d46321cSMarcel Holtmann 	       __le16_to_cpu(chan->psm), len);
24000a708f8fSGustavo F. Padovan 
24010a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24022f7719ceSAndrei Emeltchenko 
2403d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
240490338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
240590338947SGustavo Padovan 	if (IS_ERR(skb))
240690338947SGustavo Padovan 		return skb;
24070a708f8fSGustavo F. Padovan 
24080a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24094df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2410fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
2411daf6a78cSAndrei Emeltchenko 	lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE);
241243b1b8dfSMarcel Holtmann 	put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE));
24130a708f8fSGustavo F. Padovan 
24140952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24150a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24160a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24170a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24180a708f8fSGustavo F. Padovan 	}
24190a708f8fSGustavo F. Padovan 	return skb;
24200a708f8fSGustavo F. Padovan }
24210a708f8fSGustavo F. Padovan 
24225e59b791SLuiz Augusto von Dentz static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
24238d46321cSMarcel Holtmann 					      struct msghdr *msg, size_t len)
24240a708f8fSGustavo F. Padovan {
24258c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24260a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2427f2ba7faeSGustavo Padovan 	int err, count;
24280a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24290a708f8fSGustavo F. Padovan 
2430b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24310a708f8fSGustavo F. Padovan 
2432f2ba7faeSGustavo Padovan 	count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
24332f7719ceSAndrei Emeltchenko 
2434d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count,
243590338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
243690338947SGustavo Padovan 	if (IS_ERR(skb))
243790338947SGustavo Padovan 		return skb;
24380a708f8fSGustavo F. Padovan 
24390a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24404df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2441fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24426ff9b5efSGustavo Padovan 	lh->len = cpu_to_le16(len);
24430a708f8fSGustavo F. Padovan 
24440952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24450a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24460a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24470a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24480a708f8fSGustavo F. Padovan 	}
24490a708f8fSGustavo F. Padovan 	return skb;
24500a708f8fSGustavo F. Padovan }
24510a708f8fSGustavo F. Padovan 
2452ab0ff76dSLuiz Augusto von Dentz static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
2453ab0ff76dSLuiz Augusto von Dentz 					       struct msghdr *msg, size_t len,
245494122bbeSMat Martineau 					       u16 sdulen)
24550a708f8fSGustavo F. Padovan {
24568c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
24570a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
2458e4ca6d98SAndrei Emeltchenko 	int err, count, hlen;
24590a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
24600a708f8fSGustavo F. Padovan 
2461b4400672SAndrei Emeltchenko 	BT_DBG("chan %p len %zu", chan, len);
24620a708f8fSGustavo F. Padovan 
24630a708f8fSGustavo F. Padovan 	if (!conn)
24640a708f8fSGustavo F. Padovan 		return ERR_PTR(-ENOTCONN);
24650a708f8fSGustavo F. Padovan 
2466ba7aa64fSGustavo Padovan 	hlen = __ertm_hdr_size(chan);
2467e4ca6d98SAndrei Emeltchenko 
24680a708f8fSGustavo F. Padovan 	if (sdulen)
246903a51213SAndrei Emeltchenko 		hlen += L2CAP_SDULEN_SIZE;
24700a708f8fSGustavo F. Padovan 
247147d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
247203a51213SAndrei Emeltchenko 		hlen += L2CAP_FCS_SIZE;
24730a708f8fSGustavo F. Padovan 
24740a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, (conn->mtu - hlen), len);
24752f7719ceSAndrei Emeltchenko 
2476d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
247790338947SGustavo Padovan 				   msg->msg_flags & MSG_DONTWAIT);
247890338947SGustavo Padovan 	if (IS_ERR(skb))
247990338947SGustavo Padovan 		return skb;
24800a708f8fSGustavo F. Padovan 
24810a708f8fSGustavo F. Padovan 	/* Create L2CAP header */
24824df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2483fe4128e0SGustavo F. Padovan 	lh->cid = cpu_to_le16(chan->dcid);
24840a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
248588843ab0SAndrei Emeltchenko 
248618a48e76SMat Martineau 	/* Control header is populated later */
248718a48e76SMat Martineau 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
248818a48e76SMat Martineau 		put_unaligned_le32(0, skb_put(skb, L2CAP_EXT_CTRL_SIZE));
248918a48e76SMat Martineau 	else
249018a48e76SMat Martineau 		put_unaligned_le16(0, skb_put(skb, L2CAP_ENH_CTRL_SIZE));
249188843ab0SAndrei Emeltchenko 
24920a708f8fSGustavo F. Padovan 	if (sdulen)
249303a51213SAndrei Emeltchenko 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
24940a708f8fSGustavo F. Padovan 
24950952a57aSAndrei Emeltchenko 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
24960a708f8fSGustavo F. Padovan 	if (unlikely(err < 0)) {
24970a708f8fSGustavo F. Padovan 		kfree_skb(skb);
24980a708f8fSGustavo F. Padovan 		return ERR_PTR(err);
24990a708f8fSGustavo F. Padovan 	}
25000a708f8fSGustavo F. Padovan 
2501a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.fcs = chan->fcs;
2502a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.retries = 0;
25030a708f8fSGustavo F. Padovan 	return skb;
25040a708f8fSGustavo F. Padovan }
25050a708f8fSGustavo F. Padovan 
250694122bbeSMat Martineau static int l2cap_segment_sdu(struct l2cap_chan *chan,
250794122bbeSMat Martineau 			     struct sk_buff_head *seg_queue,
250894122bbeSMat Martineau 			     struct msghdr *msg, size_t len)
25090a708f8fSGustavo F. Padovan {
25100a708f8fSGustavo F. Padovan 	struct sk_buff *skb;
251194122bbeSMat Martineau 	u16 sdu_len;
251294122bbeSMat Martineau 	size_t pdu_len;
251394122bbeSMat Martineau 	u8 sar;
25140a708f8fSGustavo F. Padovan 
2515b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
25160a708f8fSGustavo F. Padovan 
251794122bbeSMat Martineau 	/* It is critical that ERTM PDUs fit in a single HCI fragment,
251894122bbeSMat Martineau 	 * so fragmented skbs are not used.  The HCI layer's handling
251994122bbeSMat Martineau 	 * of fragmented skbs is not compatible with ERTM's queueing.
252094122bbeSMat Martineau 	 */
252194122bbeSMat Martineau 
252294122bbeSMat Martineau 	/* PDU size is derived from the HCI MTU */
252394122bbeSMat Martineau 	pdu_len = chan->conn->mtu;
252494122bbeSMat Martineau 
2525a549574dSMat Martineau 	/* Constrain PDU size for BR/EDR connections */
2526a549574dSMat Martineau 	if (!chan->hs_hcon)
252794122bbeSMat Martineau 		pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
252894122bbeSMat Martineau 
252994122bbeSMat Martineau 	/* Adjust for largest possible L2CAP overhead. */
253035d401dfSGustavo Padovan 	if (chan->fcs)
253135d401dfSGustavo Padovan 		pdu_len -= L2CAP_FCS_SIZE;
253235d401dfSGustavo Padovan 
2533ba7aa64fSGustavo Padovan 	pdu_len -= __ertm_hdr_size(chan);
253494122bbeSMat Martineau 
253594122bbeSMat Martineau 	/* Remote device may have requested smaller PDUs */
253694122bbeSMat Martineau 	pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
253794122bbeSMat Martineau 
253894122bbeSMat Martineau 	if (len <= pdu_len) {
253994122bbeSMat Martineau 		sar = L2CAP_SAR_UNSEGMENTED;
254094122bbeSMat Martineau 		sdu_len = 0;
254194122bbeSMat Martineau 		pdu_len = len;
254294122bbeSMat Martineau 	} else {
254394122bbeSMat Martineau 		sar = L2CAP_SAR_START;
254494122bbeSMat Martineau 		sdu_len = len;
254594122bbeSMat Martineau 	}
25460a708f8fSGustavo F. Padovan 
25470a708f8fSGustavo F. Padovan 	while (len > 0) {
254894122bbeSMat Martineau 		skb = l2cap_create_iframe_pdu(chan, msg, pdu_len, sdu_len);
25490a708f8fSGustavo F. Padovan 
25500a708f8fSGustavo F. Padovan 		if (IS_ERR(skb)) {
255194122bbeSMat Martineau 			__skb_queue_purge(seg_queue);
25520a708f8fSGustavo F. Padovan 			return PTR_ERR(skb);
25530a708f8fSGustavo F. Padovan 		}
25540a708f8fSGustavo F. Padovan 
2555a4368ff3SJohan Hedberg 		bt_cb(skb)->l2cap.sar = sar;
255694122bbeSMat Martineau 		__skb_queue_tail(seg_queue, skb);
25570a708f8fSGustavo F. Padovan 
255894122bbeSMat Martineau 		len -= pdu_len;
2559069cb270SLukasz Rymanowski 		if (sdu_len)
256094122bbeSMat Martineau 			sdu_len = 0;
256194122bbeSMat Martineau 
256294122bbeSMat Martineau 		if (len <= pdu_len) {
256394122bbeSMat Martineau 			sar = L2CAP_SAR_END;
256494122bbeSMat Martineau 			pdu_len = len;
256594122bbeSMat Martineau 		} else {
256694122bbeSMat Martineau 			sar = L2CAP_SAR_CONTINUE;
256794122bbeSMat Martineau 		}
256894122bbeSMat Martineau 	}
256994122bbeSMat Martineau 
2570f0f62799SGustavo Padovan 	return 0;
25710a708f8fSGustavo F. Padovan }
25720a708f8fSGustavo F. Padovan 
2573177f8f2bSJohan Hedberg static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
2574177f8f2bSJohan Hedberg 						   struct msghdr *msg,
2575177f8f2bSJohan Hedberg 						   size_t len, u16 sdulen)
2576177f8f2bSJohan Hedberg {
2577177f8f2bSJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
2578177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2579177f8f2bSJohan Hedberg 	int err, count, hlen;
2580177f8f2bSJohan Hedberg 	struct l2cap_hdr *lh;
2581177f8f2bSJohan Hedberg 
2582177f8f2bSJohan Hedberg 	BT_DBG("chan %p len %zu", chan, len);
2583177f8f2bSJohan Hedberg 
2584177f8f2bSJohan Hedberg 	if (!conn)
2585177f8f2bSJohan Hedberg 		return ERR_PTR(-ENOTCONN);
2586177f8f2bSJohan Hedberg 
2587177f8f2bSJohan Hedberg 	hlen = L2CAP_HDR_SIZE;
2588177f8f2bSJohan Hedberg 
2589177f8f2bSJohan Hedberg 	if (sdulen)
2590177f8f2bSJohan Hedberg 		hlen += L2CAP_SDULEN_SIZE;
2591177f8f2bSJohan Hedberg 
2592177f8f2bSJohan Hedberg 	count = min_t(unsigned int, (conn->mtu - hlen), len);
2593177f8f2bSJohan Hedberg 
2594d9fbd02bSMarcel Holtmann 	skb = chan->ops->alloc_skb(chan, hlen, count,
2595177f8f2bSJohan Hedberg 				   msg->msg_flags & MSG_DONTWAIT);
2596177f8f2bSJohan Hedberg 	if (IS_ERR(skb))
2597177f8f2bSJohan Hedberg 		return skb;
2598177f8f2bSJohan Hedberg 
2599177f8f2bSJohan Hedberg 	/* Create L2CAP header */
26004df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
2601177f8f2bSJohan Hedberg 	lh->cid = cpu_to_le16(chan->dcid);
2602177f8f2bSJohan Hedberg 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
2603177f8f2bSJohan Hedberg 
2604177f8f2bSJohan Hedberg 	if (sdulen)
2605177f8f2bSJohan Hedberg 		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
2606177f8f2bSJohan Hedberg 
2607177f8f2bSJohan Hedberg 	err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
2608177f8f2bSJohan Hedberg 	if (unlikely(err < 0)) {
2609177f8f2bSJohan Hedberg 		kfree_skb(skb);
2610177f8f2bSJohan Hedberg 		return ERR_PTR(err);
2611177f8f2bSJohan Hedberg 	}
2612177f8f2bSJohan Hedberg 
2613177f8f2bSJohan Hedberg 	return skb;
2614177f8f2bSJohan Hedberg }
2615177f8f2bSJohan Hedberg 
2616177f8f2bSJohan Hedberg static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
2617177f8f2bSJohan Hedberg 				struct sk_buff_head *seg_queue,
2618177f8f2bSJohan Hedberg 				struct msghdr *msg, size_t len)
2619177f8f2bSJohan Hedberg {
2620177f8f2bSJohan Hedberg 	struct sk_buff *skb;
2621177f8f2bSJohan Hedberg 	size_t pdu_len;
2622177f8f2bSJohan Hedberg 	u16 sdu_len;
2623177f8f2bSJohan Hedberg 
2624177f8f2bSJohan Hedberg 	BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
2625177f8f2bSJohan Hedberg 
2626177f8f2bSJohan Hedberg 	sdu_len = len;
262772c6fb91SJohan Hedberg 	pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE;
2628177f8f2bSJohan Hedberg 
2629177f8f2bSJohan Hedberg 	while (len > 0) {
2630177f8f2bSJohan Hedberg 		if (len <= pdu_len)
2631177f8f2bSJohan Hedberg 			pdu_len = len;
2632177f8f2bSJohan Hedberg 
2633177f8f2bSJohan Hedberg 		skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
2634177f8f2bSJohan Hedberg 		if (IS_ERR(skb)) {
2635177f8f2bSJohan Hedberg 			__skb_queue_purge(seg_queue);
2636177f8f2bSJohan Hedberg 			return PTR_ERR(skb);
2637177f8f2bSJohan Hedberg 		}
2638177f8f2bSJohan Hedberg 
2639177f8f2bSJohan Hedberg 		__skb_queue_tail(seg_queue, skb);
2640177f8f2bSJohan Hedberg 
2641177f8f2bSJohan Hedberg 		len -= pdu_len;
2642177f8f2bSJohan Hedberg 
2643177f8f2bSJohan Hedberg 		if (sdu_len) {
2644177f8f2bSJohan Hedberg 			sdu_len = 0;
2645177f8f2bSJohan Hedberg 			pdu_len += L2CAP_SDULEN_SIZE;
2646177f8f2bSJohan Hedberg 		}
2647177f8f2bSJohan Hedberg 	}
2648177f8f2bSJohan Hedberg 
2649177f8f2bSJohan Hedberg 	return 0;
2650177f8f2bSJohan Hedberg }
2651177f8f2bSJohan Hedberg 
26528a505b7fSLuiz Augusto von Dentz static void l2cap_le_flowctl_send(struct l2cap_chan *chan)
26538a505b7fSLuiz Augusto von Dentz {
26548a505b7fSLuiz Augusto von Dentz 	int sent = 0;
26558a505b7fSLuiz Augusto von Dentz 
26568a505b7fSLuiz Augusto von Dentz 	BT_DBG("chan %p", chan);
26578a505b7fSLuiz Augusto von Dentz 
26588a505b7fSLuiz Augusto von Dentz 	while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
26598a505b7fSLuiz Augusto von Dentz 		l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
26608a505b7fSLuiz Augusto von Dentz 		chan->tx_credits--;
26618a505b7fSLuiz Augusto von Dentz 		sent++;
26628a505b7fSLuiz Augusto von Dentz 	}
26638a505b7fSLuiz Augusto von Dentz 
26648a505b7fSLuiz Augusto von Dentz 	BT_DBG("Sent %d credits %u queued %u", sent, chan->tx_credits,
26658a505b7fSLuiz Augusto von Dentz 	       skb_queue_len(&chan->tx_q));
26668a505b7fSLuiz Augusto von Dentz }
26678a505b7fSLuiz Augusto von Dentz 
26688d46321cSMarcel Holtmann int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
26699a91a04aSGustavo F. Padovan {
26709a91a04aSGustavo F. Padovan 	struct sk_buff *skb;
26719a91a04aSGustavo F. Padovan 	int err;
267294122bbeSMat Martineau 	struct sk_buff_head seg_queue;
26739a91a04aSGustavo F. Padovan 
267431e8ce80SSeung-Woo Kim 	if (!chan->conn)
267531e8ce80SSeung-Woo Kim 		return -ENOTCONN;
267631e8ce80SSeung-Woo Kim 
26779a91a04aSGustavo F. Padovan 	/* Connectionless channel */
2678715ec005SGustavo F. Padovan 	if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
26798d46321cSMarcel Holtmann 		skb = l2cap_create_connless_pdu(chan, msg, len);
26809a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
26819a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
26829a91a04aSGustavo F. Padovan 
26839a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
26849a91a04aSGustavo F. Padovan 		return len;
26859a91a04aSGustavo F. Padovan 	}
26869a91a04aSGustavo F. Padovan 
26879a91a04aSGustavo F. Padovan 	switch (chan->mode) {
268838319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
268915f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
2690177f8f2bSJohan Hedberg 		/* Check outgoing MTU */
2691177f8f2bSJohan Hedberg 		if (len > chan->omtu)
2692177f8f2bSJohan Hedberg 			return -EMSGSIZE;
2693177f8f2bSJohan Hedberg 
2694177f8f2bSJohan Hedberg 		__skb_queue_head_init(&seg_queue);
2695177f8f2bSJohan Hedberg 
2696177f8f2bSJohan Hedberg 		err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
2697177f8f2bSJohan Hedberg 
2698177f8f2bSJohan Hedberg 		if (chan->state != BT_CONNECTED) {
2699177f8f2bSJohan Hedberg 			__skb_queue_purge(&seg_queue);
2700177f8f2bSJohan Hedberg 			err = -ENOTCONN;
2701177f8f2bSJohan Hedberg 		}
2702177f8f2bSJohan Hedberg 
2703177f8f2bSJohan Hedberg 		if (err)
2704177f8f2bSJohan Hedberg 			return err;
2705177f8f2bSJohan Hedberg 
2706177f8f2bSJohan Hedberg 		skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
2707177f8f2bSJohan Hedberg 
27088a505b7fSLuiz Augusto von Dentz 		l2cap_le_flowctl_send(chan);
2709177f8f2bSJohan Hedberg 
2710177f8f2bSJohan Hedberg 		if (!chan->tx_credits)
2711177f8f2bSJohan Hedberg 			chan->ops->suspend(chan);
2712177f8f2bSJohan Hedberg 
2713177f8f2bSJohan Hedberg 		err = len;
2714177f8f2bSJohan Hedberg 
2715177f8f2bSJohan Hedberg 		break;
2716177f8f2bSJohan Hedberg 
2717fad5fc89SJohan Hedberg 	case L2CAP_MODE_BASIC:
27189a91a04aSGustavo F. Padovan 		/* Check outgoing MTU */
27199a91a04aSGustavo F. Padovan 		if (len > chan->omtu)
27209a91a04aSGustavo F. Padovan 			return -EMSGSIZE;
27219a91a04aSGustavo F. Padovan 
27229a91a04aSGustavo F. Padovan 		/* Create a basic PDU */
27238d46321cSMarcel Holtmann 		skb = l2cap_create_basic_pdu(chan, msg, len);
27249a91a04aSGustavo F. Padovan 		if (IS_ERR(skb))
27259a91a04aSGustavo F. Padovan 			return PTR_ERR(skb);
27269a91a04aSGustavo F. Padovan 
27279a91a04aSGustavo F. Padovan 		l2cap_do_send(chan, skb);
27289a91a04aSGustavo F. Padovan 		err = len;
27299a91a04aSGustavo F. Padovan 		break;
27309a91a04aSGustavo F. Padovan 
27319a91a04aSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
27329a91a04aSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
273394122bbeSMat Martineau 		/* Check outgoing MTU */
273494122bbeSMat Martineau 		if (len > chan->omtu) {
273594122bbeSMat Martineau 			err = -EMSGSIZE;
27369a91a04aSGustavo F. Padovan 			break;
27379a91a04aSGustavo F. Padovan 		}
27389a91a04aSGustavo F. Padovan 
273994122bbeSMat Martineau 		__skb_queue_head_init(&seg_queue);
274094122bbeSMat Martineau 
274194122bbeSMat Martineau 		/* Do segmentation before calling in to the state machine,
274294122bbeSMat Martineau 		 * since it's possible to block while waiting for memory
274394122bbeSMat Martineau 		 * allocation.
274494122bbeSMat Martineau 		 */
274594122bbeSMat Martineau 		err = l2cap_segment_sdu(chan, &seg_queue, msg, len);
274694122bbeSMat Martineau 
274794122bbeSMat Martineau 		if (err)
274894122bbeSMat Martineau 			break;
274994122bbeSMat Martineau 
27503733937dSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM)
2751d660366dSGustavo Padovan 			l2cap_tx(chan, NULL, &seg_queue, L2CAP_EV_DATA_REQUEST);
27523733937dSMat Martineau 		else
2753d660366dSGustavo Padovan 			l2cap_streaming_send(chan, &seg_queue);
275494122bbeSMat Martineau 
27559a91a04aSGustavo F. Padovan 		err = len;
27569a91a04aSGustavo F. Padovan 
275794122bbeSMat Martineau 		/* If the skbs were not queued for sending, they'll still be in
275894122bbeSMat Martineau 		 * seg_queue and need to be purged.
275994122bbeSMat Martineau 		 */
276094122bbeSMat Martineau 		__skb_queue_purge(&seg_queue);
27619a91a04aSGustavo F. Padovan 		break;
27629a91a04aSGustavo F. Padovan 
27639a91a04aSGustavo F. Padovan 	default:
27649a91a04aSGustavo F. Padovan 		BT_DBG("bad state %1.1x", chan->mode);
27659a91a04aSGustavo F. Padovan 		err = -EBADFD;
27669a91a04aSGustavo F. Padovan 	}
27679a91a04aSGustavo F. Padovan 
27689a91a04aSGustavo F. Padovan 	return err;
27699a91a04aSGustavo F. Padovan }
27706b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_send);
27719a91a04aSGustavo F. Padovan 
2772d2a7ac5dSMat Martineau static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq)
2773d2a7ac5dSMat Martineau {
2774bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2775bed68bdeSMat Martineau 	u16 seq;
2776bed68bdeSMat Martineau 
2777b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2778bed68bdeSMat Martineau 
2779bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2780bed68bdeSMat Martineau 	control.sframe = 1;
2781bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2782bed68bdeSMat Martineau 
2783bed68bdeSMat Martineau 	for (seq = chan->expected_tx_seq; seq != txseq;
2784bed68bdeSMat Martineau 	     seq = __next_seq(chan, seq)) {
2785bed68bdeSMat Martineau 		if (!l2cap_ertm_seq_in_queue(&chan->srej_q, seq)) {
2786bed68bdeSMat Martineau 			control.reqseq = seq;
2787bed68bdeSMat Martineau 			l2cap_send_sframe(chan, &control);
2788bed68bdeSMat Martineau 			l2cap_seq_list_append(&chan->srej_list, seq);
2789bed68bdeSMat Martineau 		}
2790bed68bdeSMat Martineau 	}
2791bed68bdeSMat Martineau 
2792bed68bdeSMat Martineau 	chan->expected_tx_seq = __next_seq(chan, txseq);
2793d2a7ac5dSMat Martineau }
2794d2a7ac5dSMat Martineau 
2795d2a7ac5dSMat Martineau static void l2cap_send_srej_tail(struct l2cap_chan *chan)
2796d2a7ac5dSMat Martineau {
2797bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2798bed68bdeSMat Martineau 
2799bed68bdeSMat Martineau 	BT_DBG("chan %p", chan);
2800bed68bdeSMat Martineau 
2801bed68bdeSMat Martineau 	if (chan->srej_list.tail == L2CAP_SEQ_LIST_CLEAR)
2802bed68bdeSMat Martineau 		return;
2803bed68bdeSMat Martineau 
2804bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2805bed68bdeSMat Martineau 	control.sframe = 1;
2806bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2807bed68bdeSMat Martineau 	control.reqseq = chan->srej_list.tail;
2808bed68bdeSMat Martineau 	l2cap_send_sframe(chan, &control);
2809d2a7ac5dSMat Martineau }
2810d2a7ac5dSMat Martineau 
2811d2a7ac5dSMat Martineau static void l2cap_send_srej_list(struct l2cap_chan *chan, u16 txseq)
2812d2a7ac5dSMat Martineau {
2813bed68bdeSMat Martineau 	struct l2cap_ctrl control;
2814bed68bdeSMat Martineau 	u16 initial_head;
2815bed68bdeSMat Martineau 	u16 seq;
2816bed68bdeSMat Martineau 
2817b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, txseq %u", chan, txseq);
2818bed68bdeSMat Martineau 
2819bed68bdeSMat Martineau 	memset(&control, 0, sizeof(control));
2820bed68bdeSMat Martineau 	control.sframe = 1;
2821bed68bdeSMat Martineau 	control.super = L2CAP_SUPER_SREJ;
2822bed68bdeSMat Martineau 
2823bed68bdeSMat Martineau 	/* Capture initial list head to allow only one pass through the list. */
2824bed68bdeSMat Martineau 	initial_head = chan->srej_list.head;
2825bed68bdeSMat Martineau 
2826bed68bdeSMat Martineau 	do {
2827bed68bdeSMat Martineau 		seq = l2cap_seq_list_pop(&chan->srej_list);
2828bed68bdeSMat Martineau 		if (seq == txseq || seq == L2CAP_SEQ_LIST_CLEAR)
2829bed68bdeSMat Martineau 			break;
2830bed68bdeSMat Martineau 
2831bed68bdeSMat Martineau 		control.reqseq = seq;
2832bed68bdeSMat Martineau 		l2cap_send_sframe(chan, &control);
2833bed68bdeSMat Martineau 		l2cap_seq_list_append(&chan->srej_list, seq);
2834bed68bdeSMat Martineau 	} while (chan->srej_list.head != initial_head);
2835d2a7ac5dSMat Martineau }
2836d2a7ac5dSMat Martineau 
2837608bcc6dSMat Martineau static void l2cap_process_reqseq(struct l2cap_chan *chan, u16 reqseq)
2838608bcc6dSMat Martineau {
2839608bcc6dSMat Martineau 	struct sk_buff *acked_skb;
2840608bcc6dSMat Martineau 	u16 ackseq;
2841608bcc6dSMat Martineau 
2842b4400672SAndrei Emeltchenko 	BT_DBG("chan %p, reqseq %u", chan, reqseq);
2843608bcc6dSMat Martineau 
2844608bcc6dSMat Martineau 	if (chan->unacked_frames == 0 || reqseq == chan->expected_ack_seq)
2845608bcc6dSMat Martineau 		return;
2846608bcc6dSMat Martineau 
2847b4400672SAndrei Emeltchenko 	BT_DBG("expected_ack_seq %u, unacked_frames %u",
2848608bcc6dSMat Martineau 	       chan->expected_ack_seq, chan->unacked_frames);
2849608bcc6dSMat Martineau 
2850608bcc6dSMat Martineau 	for (ackseq = chan->expected_ack_seq; ackseq != reqseq;
2851608bcc6dSMat Martineau 	     ackseq = __next_seq(chan, ackseq)) {
2852608bcc6dSMat Martineau 
2853608bcc6dSMat Martineau 		acked_skb = l2cap_ertm_seq_in_queue(&chan->tx_q, ackseq);
2854608bcc6dSMat Martineau 		if (acked_skb) {
2855608bcc6dSMat Martineau 			skb_unlink(acked_skb, &chan->tx_q);
2856608bcc6dSMat Martineau 			kfree_skb(acked_skb);
2857608bcc6dSMat Martineau 			chan->unacked_frames--;
2858608bcc6dSMat Martineau 		}
2859608bcc6dSMat Martineau 	}
2860608bcc6dSMat Martineau 
2861608bcc6dSMat Martineau 	chan->expected_ack_seq = reqseq;
2862608bcc6dSMat Martineau 
2863608bcc6dSMat Martineau 	if (chan->unacked_frames == 0)
2864608bcc6dSMat Martineau 		__clear_retrans_timer(chan);
2865608bcc6dSMat Martineau 
2866b4400672SAndrei Emeltchenko 	BT_DBG("unacked_frames %u", chan->unacked_frames);
2867608bcc6dSMat Martineau }
2868608bcc6dSMat Martineau 
2869608bcc6dSMat Martineau static void l2cap_abort_rx_srej_sent(struct l2cap_chan *chan)
2870608bcc6dSMat Martineau {
2871608bcc6dSMat Martineau 	BT_DBG("chan %p", chan);
2872608bcc6dSMat Martineau 
2873608bcc6dSMat Martineau 	chan->expected_tx_seq = chan->buffer_seq;
2874608bcc6dSMat Martineau 	l2cap_seq_list_clear(&chan->srej_list);
2875608bcc6dSMat Martineau 	skb_queue_purge(&chan->srej_q);
2876608bcc6dSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
2877608bcc6dSMat Martineau }
2878608bcc6dSMat Martineau 
2879d660366dSGustavo Padovan static void l2cap_tx_state_xmit(struct l2cap_chan *chan,
2880608bcc6dSMat Martineau 				struct l2cap_ctrl *control,
2881608bcc6dSMat Martineau 				struct sk_buff_head *skbs, u8 event)
2882608bcc6dSMat Martineau {
2883608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2884608bcc6dSMat Martineau 	       event);
2885608bcc6dSMat Martineau 
2886608bcc6dSMat Martineau 	switch (event) {
2887608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2888608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2889608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2890608bcc6dSMat Martineau 
2891608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2892608bcc6dSMat Martineau 		l2cap_ertm_send(chan);
2893608bcc6dSMat Martineau 		break;
2894608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2895608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2896608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2897608bcc6dSMat Martineau 
2898608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2899608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2900608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2901608bcc6dSMat Martineau 			 */
2902608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2903608bcc6dSMat Martineau 		}
2904608bcc6dSMat Martineau 
2905608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2906608bcc6dSMat Martineau 
2907608bcc6dSMat Martineau 		break;
2908608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2909608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2910608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2911608bcc6dSMat Martineau 
2912608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2913608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2914608bcc6dSMat Martineau 
2915608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2916608bcc6dSMat Martineau 			local_control.sframe = 1;
2917608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2918608bcc6dSMat Martineau 			local_control.poll = 1;
2919608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2920a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2921608bcc6dSMat Martineau 
2922608bcc6dSMat Martineau 			chan->retry_count = 1;
2923608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2924608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2925608bcc6dSMat Martineau 		}
2926608bcc6dSMat Martineau 		break;
2927608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2928608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
2929608bcc6dSMat Martineau 		break;
2930608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
2931608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2932608bcc6dSMat Martineau 		chan->retry_count = 1;
2933608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2934608bcc6dSMat Martineau 		__clear_ack_timer(chan);
2935608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2936608bcc6dSMat Martineau 		break;
2937608bcc6dSMat Martineau 	case L2CAP_EV_RETRANS_TO:
2938608bcc6dSMat Martineau 		l2cap_send_rr_or_rnr(chan, 1);
2939608bcc6dSMat Martineau 		chan->retry_count = 1;
2940608bcc6dSMat Martineau 		__set_monitor_timer(chan);
2941608bcc6dSMat Martineau 		chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2942608bcc6dSMat Martineau 		break;
2943608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
2944608bcc6dSMat Martineau 		/* Nothing to process */
2945608bcc6dSMat Martineau 		break;
2946608bcc6dSMat Martineau 	default:
2947608bcc6dSMat Martineau 		break;
2948608bcc6dSMat Martineau 	}
2949608bcc6dSMat Martineau }
2950608bcc6dSMat Martineau 
2951d660366dSGustavo Padovan static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
2952608bcc6dSMat Martineau 				  struct l2cap_ctrl *control,
2953608bcc6dSMat Martineau 				  struct sk_buff_head *skbs, u8 event)
2954608bcc6dSMat Martineau {
2955608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d", chan, control, skbs,
2956608bcc6dSMat Martineau 	       event);
2957608bcc6dSMat Martineau 
2958608bcc6dSMat Martineau 	switch (event) {
2959608bcc6dSMat Martineau 	case L2CAP_EV_DATA_REQUEST:
2960608bcc6dSMat Martineau 		if (chan->tx_send_head == NULL)
2961608bcc6dSMat Martineau 			chan->tx_send_head = skb_peek(skbs);
2962608bcc6dSMat Martineau 		/* Queue data, but don't send. */
2963608bcc6dSMat Martineau 		skb_queue_splice_tail_init(skbs, &chan->tx_q);
2964608bcc6dSMat Martineau 		break;
2965608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_DETECTED:
2966608bcc6dSMat Martineau 		BT_DBG("Enter LOCAL_BUSY");
2967608bcc6dSMat Martineau 		set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2968608bcc6dSMat Martineau 
2969608bcc6dSMat Martineau 		if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
2970608bcc6dSMat Martineau 			/* The SREJ_SENT state must be aborted if we are to
2971608bcc6dSMat Martineau 			 * enter the LOCAL_BUSY state.
2972608bcc6dSMat Martineau 			 */
2973608bcc6dSMat Martineau 			l2cap_abort_rx_srej_sent(chan);
2974608bcc6dSMat Martineau 		}
2975608bcc6dSMat Martineau 
2976608bcc6dSMat Martineau 		l2cap_send_ack(chan);
2977608bcc6dSMat Martineau 
2978608bcc6dSMat Martineau 		break;
2979608bcc6dSMat Martineau 	case L2CAP_EV_LOCAL_BUSY_CLEAR:
2980608bcc6dSMat Martineau 		BT_DBG("Exit LOCAL_BUSY");
2981608bcc6dSMat Martineau 		clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
2982608bcc6dSMat Martineau 
2983608bcc6dSMat Martineau 		if (test_bit(CONN_RNR_SENT, &chan->conn_state)) {
2984608bcc6dSMat Martineau 			struct l2cap_ctrl local_control;
2985608bcc6dSMat Martineau 			memset(&local_control, 0, sizeof(local_control));
2986608bcc6dSMat Martineau 			local_control.sframe = 1;
2987608bcc6dSMat Martineau 			local_control.super = L2CAP_SUPER_RR;
2988608bcc6dSMat Martineau 			local_control.poll = 1;
2989608bcc6dSMat Martineau 			local_control.reqseq = chan->buffer_seq;
2990a67d7f6fSMat Martineau 			l2cap_send_sframe(chan, &local_control);
2991608bcc6dSMat Martineau 
2992608bcc6dSMat Martineau 			chan->retry_count = 1;
2993608bcc6dSMat Martineau 			__set_monitor_timer(chan);
2994608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_WAIT_F;
2995608bcc6dSMat Martineau 		}
2996608bcc6dSMat Martineau 		break;
2997608bcc6dSMat Martineau 	case L2CAP_EV_RECV_REQSEQ_AND_FBIT:
2998608bcc6dSMat Martineau 		l2cap_process_reqseq(chan, control->reqseq);
299919186c7bSGustavo A. R. Silva 		fallthrough;
3000608bcc6dSMat Martineau 
3001608bcc6dSMat Martineau 	case L2CAP_EV_RECV_FBIT:
3002608bcc6dSMat Martineau 		if (control && control->final) {
3003608bcc6dSMat Martineau 			__clear_monitor_timer(chan);
3004608bcc6dSMat Martineau 			if (chan->unacked_frames > 0)
3005608bcc6dSMat Martineau 				__set_retrans_timer(chan);
3006608bcc6dSMat Martineau 			chan->retry_count = 0;
3007608bcc6dSMat Martineau 			chan->tx_state = L2CAP_TX_STATE_XMIT;
3008608bcc6dSMat Martineau 			BT_DBG("recv fbit tx_state 0x2.2%x", chan->tx_state);
3009608bcc6dSMat Martineau 		}
3010608bcc6dSMat Martineau 		break;
3011608bcc6dSMat Martineau 	case L2CAP_EV_EXPLICIT_POLL:
3012608bcc6dSMat Martineau 		/* Ignore */
3013608bcc6dSMat Martineau 		break;
3014608bcc6dSMat Martineau 	case L2CAP_EV_MONITOR_TO:
3015608bcc6dSMat Martineau 		if (chan->max_tx == 0 || chan->retry_count < chan->max_tx) {
3016608bcc6dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 1);
3017608bcc6dSMat Martineau 			__set_monitor_timer(chan);
3018608bcc6dSMat Martineau 			chan->retry_count++;
3019608bcc6dSMat Martineau 		} else {
30205e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNABORTED);
3021608bcc6dSMat Martineau 		}
3022608bcc6dSMat Martineau 		break;
3023608bcc6dSMat Martineau 	default:
3024608bcc6dSMat Martineau 		break;
3025608bcc6dSMat Martineau 	}
3026608bcc6dSMat Martineau }
3027608bcc6dSMat Martineau 
3028d660366dSGustavo Padovan static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
3029608bcc6dSMat Martineau 		     struct sk_buff_head *skbs, u8 event)
3030608bcc6dSMat Martineau {
3031608bcc6dSMat Martineau 	BT_DBG("chan %p, control %p, skbs %p, event %d, state %d",
3032608bcc6dSMat Martineau 	       chan, control, skbs, event, chan->tx_state);
3033608bcc6dSMat Martineau 
3034608bcc6dSMat Martineau 	switch (chan->tx_state) {
3035608bcc6dSMat Martineau 	case L2CAP_TX_STATE_XMIT:
3036d660366dSGustavo Padovan 		l2cap_tx_state_xmit(chan, control, skbs, event);
3037608bcc6dSMat Martineau 		break;
3038608bcc6dSMat Martineau 	case L2CAP_TX_STATE_WAIT_F:
3039d660366dSGustavo Padovan 		l2cap_tx_state_wait_f(chan, control, skbs, event);
3040608bcc6dSMat Martineau 		break;
3041608bcc6dSMat Martineau 	default:
3042608bcc6dSMat Martineau 		/* Ignore event */
3043608bcc6dSMat Martineau 		break;
3044608bcc6dSMat Martineau 	}
3045608bcc6dSMat Martineau }
3046608bcc6dSMat Martineau 
30474b51dae9SMat Martineau static void l2cap_pass_to_tx(struct l2cap_chan *chan,
30484b51dae9SMat Martineau 			     struct l2cap_ctrl *control)
30494b51dae9SMat Martineau {
30504b51dae9SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3051401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_REQSEQ_AND_FBIT);
30524b51dae9SMat Martineau }
30534b51dae9SMat Martineau 
3054f80842a8SMat Martineau static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan,
3055f80842a8SMat Martineau 				  struct l2cap_ctrl *control)
3056f80842a8SMat Martineau {
3057f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
3058401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, control, NULL, L2CAP_EV_RECV_FBIT);
3059f80842a8SMat Martineau }
3060f80842a8SMat Martineau 
30610a708f8fSGustavo F. Padovan /* Copy frame to all raw sockets on that connection */
30620a708f8fSGustavo F. Padovan static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
30630a708f8fSGustavo F. Padovan {
30640a708f8fSGustavo F. Padovan 	struct sk_buff *nskb;
306548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
30660a708f8fSGustavo F. Padovan 
30670a708f8fSGustavo F. Padovan 	BT_DBG("conn %p", conn);
30680a708f8fSGustavo F. Padovan 
30693df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
30703d57dc68SGustavo F. Padovan 
30713df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
3072715ec005SGustavo F. Padovan 		if (chan->chan_type != L2CAP_CHAN_RAW)
30730a708f8fSGustavo F. Padovan 			continue;
30740a708f8fSGustavo F. Padovan 
30757f5396a7SGustavo Padovan 		/* Don't send frame to the channel it came from */
3076a4368ff3SJohan Hedberg 		if (bt_cb(skb)->l2cap.chan == chan)
30770a708f8fSGustavo F. Padovan 			continue;
30787f5396a7SGustavo Padovan 
30798bcde1f2SGustavo Padovan 		nskb = skb_clone(skb, GFP_KERNEL);
30800a708f8fSGustavo F. Padovan 		if (!nskb)
30810a708f8fSGustavo F. Padovan 			continue;
308280b98027SGustavo Padovan 		if (chan->ops->recv(chan, nskb))
30830a708f8fSGustavo F. Padovan 			kfree_skb(nskb);
30840a708f8fSGustavo F. Padovan 	}
30853d57dc68SGustavo F. Padovan 
30863df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
30870a708f8fSGustavo F. Padovan }
30880a708f8fSGustavo F. Padovan 
30890a708f8fSGustavo F. Padovan /* ---- L2CAP signalling commands ---- */
3090b4400672SAndrei Emeltchenko static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
3091b4400672SAndrei Emeltchenko 				       u8 ident, u16 dlen, void *data)
30920a708f8fSGustavo F. Padovan {
30930a708f8fSGustavo F. Padovan 	struct sk_buff *skb, **frag;
30940a708f8fSGustavo F. Padovan 	struct l2cap_cmd_hdr *cmd;
30950a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh;
30960a708f8fSGustavo F. Padovan 	int len, count;
30970a708f8fSGustavo F. Padovan 
3098b4400672SAndrei Emeltchenko 	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
30990a708f8fSGustavo F. Padovan 	       conn, code, ident, dlen);
31000a708f8fSGustavo F. Padovan 
3101300b962eSAnderson Lizardo 	if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
3102300b962eSAnderson Lizardo 		return NULL;
3103300b962eSAnderson Lizardo 
31040a708f8fSGustavo F. Padovan 	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
31050a708f8fSGustavo F. Padovan 	count = min_t(unsigned int, conn->mtu, len);
31060a708f8fSGustavo F. Padovan 
31078bcde1f2SGustavo Padovan 	skb = bt_skb_alloc(count, GFP_KERNEL);
31080a708f8fSGustavo F. Padovan 	if (!skb)
31090a708f8fSGustavo F. Padovan 		return NULL;
31100a708f8fSGustavo F. Padovan 
31114df864c1SJohannes Berg 	lh = skb_put(skb, L2CAP_HDR_SIZE);
31120a708f8fSGustavo F. Padovan 	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
31133300d9a9SClaudio Takahasi 
31143300d9a9SClaudio Takahasi 	if (conn->hcon->type == LE_LINK)
3115dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
31163300d9a9SClaudio Takahasi 	else
3117dcf4adbfSJoe Perches 		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
31180a708f8fSGustavo F. Padovan 
31194df864c1SJohannes Berg 	cmd = skb_put(skb, L2CAP_CMD_HDR_SIZE);
31200a708f8fSGustavo F. Padovan 	cmd->code  = code;
31210a708f8fSGustavo F. Padovan 	cmd->ident = ident;
31220a708f8fSGustavo F. Padovan 	cmd->len   = cpu_to_le16(dlen);
31230a708f8fSGustavo F. Padovan 
31240a708f8fSGustavo F. Padovan 	if (dlen) {
31250a708f8fSGustavo F. Padovan 		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
312659ae1d12SJohannes Berg 		skb_put_data(skb, data, count);
31270a708f8fSGustavo F. Padovan 		data += count;
31280a708f8fSGustavo F. Padovan 	}
31290a708f8fSGustavo F. Padovan 
31300a708f8fSGustavo F. Padovan 	len -= skb->len;
31310a708f8fSGustavo F. Padovan 
31320a708f8fSGustavo F. Padovan 	/* Continuation fragments (no L2CAP header) */
31330a708f8fSGustavo F. Padovan 	frag = &skb_shinfo(skb)->frag_list;
31340a708f8fSGustavo F. Padovan 	while (len) {
31350a708f8fSGustavo F. Padovan 		count = min_t(unsigned int, conn->mtu, len);
31360a708f8fSGustavo F. Padovan 
31378bcde1f2SGustavo Padovan 		*frag = bt_skb_alloc(count, GFP_KERNEL);
31380a708f8fSGustavo F. Padovan 		if (!*frag)
31390a708f8fSGustavo F. Padovan 			goto fail;
31400a708f8fSGustavo F. Padovan 
314159ae1d12SJohannes Berg 		skb_put_data(*frag, data, count);
31420a708f8fSGustavo F. Padovan 
31430a708f8fSGustavo F. Padovan 		len  -= count;
31440a708f8fSGustavo F. Padovan 		data += count;
31450a708f8fSGustavo F. Padovan 
31460a708f8fSGustavo F. Padovan 		frag = &(*frag)->next;
31470a708f8fSGustavo F. Padovan 	}
31480a708f8fSGustavo F. Padovan 
31490a708f8fSGustavo F. Padovan 	return skb;
31500a708f8fSGustavo F. Padovan 
31510a708f8fSGustavo F. Padovan fail:
31520a708f8fSGustavo F. Padovan 	kfree_skb(skb);
31530a708f8fSGustavo F. Padovan 	return NULL;
31540a708f8fSGustavo F. Padovan }
31550a708f8fSGustavo F. Padovan 
31562d792818SGustavo Padovan static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
31572d792818SGustavo Padovan 				     unsigned long *val)
31580a708f8fSGustavo F. Padovan {
31590a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31600a708f8fSGustavo F. Padovan 	int len;
31610a708f8fSGustavo F. Padovan 
31620a708f8fSGustavo F. Padovan 	len = L2CAP_CONF_OPT_SIZE + opt->len;
31630a708f8fSGustavo F. Padovan 	*ptr += len;
31640a708f8fSGustavo F. Padovan 
31650a708f8fSGustavo F. Padovan 	*type = opt->type;
31660a708f8fSGustavo F. Padovan 	*olen = opt->len;
31670a708f8fSGustavo F. Padovan 
31680a708f8fSGustavo F. Padovan 	switch (opt->len) {
31690a708f8fSGustavo F. Padovan 	case 1:
31700a708f8fSGustavo F. Padovan 		*val = *((u8 *) opt->val);
31710a708f8fSGustavo F. Padovan 		break;
31720a708f8fSGustavo F. Padovan 
31730a708f8fSGustavo F. Padovan 	case 2:
31740a708f8fSGustavo F. Padovan 		*val = get_unaligned_le16(opt->val);
31750a708f8fSGustavo F. Padovan 		break;
31760a708f8fSGustavo F. Padovan 
31770a708f8fSGustavo F. Padovan 	case 4:
31780a708f8fSGustavo F. Padovan 		*val = get_unaligned_le32(opt->val);
31790a708f8fSGustavo F. Padovan 		break;
31800a708f8fSGustavo F. Padovan 
31810a708f8fSGustavo F. Padovan 	default:
31820a708f8fSGustavo F. Padovan 		*val = (unsigned long) opt->val;
31830a708f8fSGustavo F. Padovan 		break;
31840a708f8fSGustavo F. Padovan 	}
31850a708f8fSGustavo F. Padovan 
3186b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", *type, opt->len, *val);
31870a708f8fSGustavo F. Padovan 	return len;
31880a708f8fSGustavo F. Padovan }
31890a708f8fSGustavo F. Padovan 
3190e860d2c9SBen Seri static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
31910a708f8fSGustavo F. Padovan {
31920a708f8fSGustavo F. Padovan 	struct l2cap_conf_opt *opt = *ptr;
31930a708f8fSGustavo F. Padovan 
3194b4400672SAndrei Emeltchenko 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
31950a708f8fSGustavo F. Padovan 
3196e860d2c9SBen Seri 	if (size < L2CAP_CONF_OPT_SIZE + len)
3197e860d2c9SBen Seri 		return;
3198e860d2c9SBen Seri 
31990a708f8fSGustavo F. Padovan 	opt->type = type;
32000a708f8fSGustavo F. Padovan 	opt->len  = len;
32010a708f8fSGustavo F. Padovan 
32020a708f8fSGustavo F. Padovan 	switch (len) {
32030a708f8fSGustavo F. Padovan 	case 1:
32040a708f8fSGustavo F. Padovan 		*((u8 *) opt->val)  = val;
32050a708f8fSGustavo F. Padovan 		break;
32060a708f8fSGustavo F. Padovan 
32070a708f8fSGustavo F. Padovan 	case 2:
32080a708f8fSGustavo F. Padovan 		put_unaligned_le16(val, opt->val);
32090a708f8fSGustavo F. Padovan 		break;
32100a708f8fSGustavo F. Padovan 
32110a708f8fSGustavo F. Padovan 	case 4:
32120a708f8fSGustavo F. Padovan 		put_unaligned_le32(val, opt->val);
32130a708f8fSGustavo F. Padovan 		break;
32140a708f8fSGustavo F. Padovan 
32150a708f8fSGustavo F. Padovan 	default:
32160a708f8fSGustavo F. Padovan 		memcpy(opt->val, (void *) val, len);
32170a708f8fSGustavo F. Padovan 		break;
32180a708f8fSGustavo F. Padovan 	}
32190a708f8fSGustavo F. Padovan 
32200a708f8fSGustavo F. Padovan 	*ptr += L2CAP_CONF_OPT_SIZE + len;
32210a708f8fSGustavo F. Padovan }
32220a708f8fSGustavo F. Padovan 
3223e860d2c9SBen Seri static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
3224f89cef09SAndrei Emeltchenko {
3225f89cef09SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
3226f89cef09SAndrei Emeltchenko 
3227f89cef09SAndrei Emeltchenko 	switch (chan->mode) {
3228f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_ERTM:
3229f89cef09SAndrei Emeltchenko 		efs.id		= chan->local_id;
3230f89cef09SAndrei Emeltchenko 		efs.stype	= chan->local_stype;
3231f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3232f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3233dcf4adbfSJoe Perches 		efs.acc_lat	= cpu_to_le32(L2CAP_DEFAULT_ACC_LAT);
3234dcf4adbfSJoe Perches 		efs.flush_to	= cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO);
3235f89cef09SAndrei Emeltchenko 		break;
3236f89cef09SAndrei Emeltchenko 
3237f89cef09SAndrei Emeltchenko 	case L2CAP_MODE_STREAMING:
3238f89cef09SAndrei Emeltchenko 		efs.id		= 1;
3239f89cef09SAndrei Emeltchenko 		efs.stype	= L2CAP_SERV_BESTEFFORT;
3240f89cef09SAndrei Emeltchenko 		efs.msdu	= cpu_to_le16(chan->local_msdu);
3241f89cef09SAndrei Emeltchenko 		efs.sdu_itime	= cpu_to_le32(chan->local_sdu_itime);
3242f89cef09SAndrei Emeltchenko 		efs.acc_lat	= 0;
3243f89cef09SAndrei Emeltchenko 		efs.flush_to	= 0;
3244f89cef09SAndrei Emeltchenko 		break;
3245f89cef09SAndrei Emeltchenko 
3246f89cef09SAndrei Emeltchenko 	default:
3247f89cef09SAndrei Emeltchenko 		return;
3248f89cef09SAndrei Emeltchenko 	}
3249f89cef09SAndrei Emeltchenko 
3250f89cef09SAndrei Emeltchenko 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3251e860d2c9SBen Seri 			   (unsigned long) &efs, size);
3252f89cef09SAndrei Emeltchenko }
3253f89cef09SAndrei Emeltchenko 
3254721c4181SGustavo F. Padovan static void l2cap_ack_timeout(struct work_struct *work)
32550a708f8fSGustavo F. Padovan {
3256721c4181SGustavo F. Padovan 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
3257721c4181SGustavo F. Padovan 					       ack_timer.work);
32580362520bSMat Martineau 	u16 frames_to_ack;
32590a708f8fSGustavo F. Padovan 
32602fb9b3d4SGustavo F. Padovan 	BT_DBG("chan %p", chan);
32612fb9b3d4SGustavo F. Padovan 
32626be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
32636be36555SAndrei Emeltchenko 
32640362520bSMat Martineau 	frames_to_ack = __seq_offset(chan, chan->buffer_seq,
32650362520bSMat Martineau 				     chan->last_acked_seq);
32660362520bSMat Martineau 
32670362520bSMat Martineau 	if (frames_to_ack)
32680362520bSMat Martineau 		l2cap_send_rr_or_rnr(chan, 0);
32696be36555SAndrei Emeltchenko 
32706be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
327109bfb2eeSSzymon Janc 	l2cap_chan_put(chan);
32720a708f8fSGustavo F. Padovan }
32730a708f8fSGustavo F. Padovan 
3274466f8004SAndrei Emeltchenko int l2cap_ertm_init(struct l2cap_chan *chan)
32750a708f8fSGustavo F. Padovan {
32763c588192SMat Martineau 	int err;
32773c588192SMat Martineau 
3278105bdf9eSMat Martineau 	chan->next_tx_seq = 0;
3279105bdf9eSMat Martineau 	chan->expected_tx_seq = 0;
328042e5c802SGustavo F. Padovan 	chan->expected_ack_seq = 0;
32816a026610SGustavo F. Padovan 	chan->unacked_frames = 0;
328242e5c802SGustavo F. Padovan 	chan->buffer_seq = 0;
32836a026610SGustavo F. Padovan 	chan->frames_sent = 0;
3284105bdf9eSMat Martineau 	chan->last_acked_seq = 0;
3285105bdf9eSMat Martineau 	chan->sdu = NULL;
3286105bdf9eSMat Martineau 	chan->sdu_last_frag = NULL;
3287105bdf9eSMat Martineau 	chan->sdu_len = 0;
3288105bdf9eSMat Martineau 
3289d34c34fbSMat Martineau 	skb_queue_head_init(&chan->tx_q);
3290d34c34fbSMat Martineau 
32916ed971caSMarcel Holtmann 	chan->local_amp_id = AMP_ID_BREDR;
32926ed971caSMarcel Holtmann 	chan->move_id = AMP_ID_BREDR;
329308333283SMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
329408333283SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
329508333283SMat Martineau 
3296105bdf9eSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
3297105bdf9eSMat Martineau 		return 0;
3298105bdf9eSMat Martineau 
3299105bdf9eSMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
3300105bdf9eSMat Martineau 	chan->tx_state = L2CAP_TX_STATE_XMIT;
33010a708f8fSGustavo F. Padovan 
3302f1c6775bSGustavo F. Padovan 	skb_queue_head_init(&chan->srej_q);
33030a708f8fSGustavo F. Padovan 
33043c588192SMat Martineau 	err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win);
33053c588192SMat Martineau 	if (err < 0)
33063c588192SMat Martineau 		return err;
33073c588192SMat Martineau 
33089dc9affcSMat Martineau 	err = l2cap_seq_list_init(&chan->retrans_list, chan->remote_tx_win);
33099dc9affcSMat Martineau 	if (err < 0)
33109dc9affcSMat Martineau 		l2cap_seq_list_free(&chan->srej_list);
33119dc9affcSMat Martineau 
33129dc9affcSMat Martineau 	return err;
33130a708f8fSGustavo F. Padovan }
33140a708f8fSGustavo F. Padovan 
33150a708f8fSGustavo F. Padovan static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
33160a708f8fSGustavo F. Padovan {
33170a708f8fSGustavo F. Padovan 	switch (mode) {
33180a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
33190a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
33200a708f8fSGustavo F. Padovan 		if (l2cap_mode_supported(mode, remote_feat_mask))
33210a708f8fSGustavo F. Padovan 			return mode;
332219186c7bSGustavo A. R. Silva 		fallthrough;
33230a708f8fSGustavo F. Padovan 	default:
33240a708f8fSGustavo F. Padovan 		return L2CAP_MODE_BASIC;
33250a708f8fSGustavo F. Padovan 	}
33260a708f8fSGustavo F. Padovan }
33270a708f8fSGustavo F. Padovan 
3328848566b3SMarcel Holtmann static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
33296327eb98SAndrei Emeltchenko {
33300bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33310bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
33326327eb98SAndrei Emeltchenko }
33336327eb98SAndrei Emeltchenko 
3334848566b3SMarcel Holtmann static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
3335f89cef09SAndrei Emeltchenko {
33360bd49fc7SJohan Hedberg 	return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
33370bd49fc7SJohan Hedberg 		(conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
3338f89cef09SAndrei Emeltchenko }
3339f89cef09SAndrei Emeltchenko 
334036c86c85SMat Martineau static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
334136c86c85SMat Martineau 				      struct l2cap_conf_rfc *rfc)
334236c86c85SMat Martineau {
33436ed971caSMarcel Holtmann 	if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
334436c86c85SMat Martineau 		u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
334536c86c85SMat Martineau 
334636c86c85SMat Martineau 		/* Class 1 devices have must have ERTM timeouts
334736c86c85SMat Martineau 		 * exceeding the Link Supervision Timeout.  The
334836c86c85SMat Martineau 		 * default Link Supervision Timeout for AMP
334936c86c85SMat Martineau 		 * controllers is 10 seconds.
335036c86c85SMat Martineau 		 *
335136c86c85SMat Martineau 		 * Class 1 devices use 0xffffffff for their
335236c86c85SMat Martineau 		 * best-effort flush timeout, so the clamping logic
335336c86c85SMat Martineau 		 * will result in a timeout that meets the above
335436c86c85SMat Martineau 		 * requirement.  ERTM timeouts are 16-bit values, so
335536c86c85SMat Martineau 		 * the maximum timeout is 65.535 seconds.
335636c86c85SMat Martineau 		 */
335736c86c85SMat Martineau 
335836c86c85SMat Martineau 		/* Convert timeout to milliseconds and round */
335936c86c85SMat Martineau 		ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
336036c86c85SMat Martineau 
336136c86c85SMat Martineau 		/* This is the recommended formula for class 2 devices
336236c86c85SMat Martineau 		 * that start ERTM timers when packets are sent to the
336336c86c85SMat Martineau 		 * controller.
336436c86c85SMat Martineau 		 */
336536c86c85SMat Martineau 		ertm_to = 3 * ertm_to + 500;
336636c86c85SMat Martineau 
336736c86c85SMat Martineau 		if (ertm_to > 0xffff)
336836c86c85SMat Martineau 			ertm_to = 0xffff;
336936c86c85SMat Martineau 
337036c86c85SMat Martineau 		rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
337136c86c85SMat Martineau 		rfc->monitor_timeout = rfc->retrans_timeout;
337236c86c85SMat Martineau 	} else {
3373dcf4adbfSJoe Perches 		rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
3374dcf4adbfSJoe Perches 		rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
337536c86c85SMat Martineau 	}
337636c86c85SMat Martineau }
337736c86c85SMat Martineau 
33786327eb98SAndrei Emeltchenko static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
33796327eb98SAndrei Emeltchenko {
33806327eb98SAndrei Emeltchenko 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
3381848566b3SMarcel Holtmann 	    __l2cap_ews_supported(chan->conn)) {
33826327eb98SAndrei Emeltchenko 		/* use extended control field */
33836327eb98SAndrei Emeltchenko 		set_bit(FLAG_EXT_CTRL, &chan->flags);
3384836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
3385836be934SAndrei Emeltchenko 	} else {
33866327eb98SAndrei Emeltchenko 		chan->tx_win = min_t(u16, chan->tx_win,
33876327eb98SAndrei Emeltchenko 				     L2CAP_DEFAULT_TX_WINDOW);
3388836be934SAndrei Emeltchenko 		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
3389836be934SAndrei Emeltchenko 	}
3390c20f8e35SMat Martineau 	chan->ack_win = chan->tx_win;
33916327eb98SAndrei Emeltchenko }
33926327eb98SAndrei Emeltchenko 
33934b6e228eSLuiz Augusto von Dentz static void l2cap_mtu_auto(struct l2cap_chan *chan)
33944b6e228eSLuiz Augusto von Dentz {
33954b6e228eSLuiz Augusto von Dentz 	struct hci_conn *conn = chan->conn->hcon;
33964b6e228eSLuiz Augusto von Dentz 
33974b6e228eSLuiz Augusto von Dentz 	chan->imtu = L2CAP_DEFAULT_MIN_MTU;
33984b6e228eSLuiz Augusto von Dentz 
33994b6e228eSLuiz Augusto von Dentz 	/* The 2-DH1 packet has between 2 and 56 information bytes
34004b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34014b6e228eSLuiz Augusto von Dentz 	 */
34024b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH1))
34034b6e228eSLuiz Augusto von Dentz 		chan->imtu = 54;
34044b6e228eSLuiz Augusto von Dentz 
34054b6e228eSLuiz Augusto von Dentz 	/* The 3-DH1 packet has between 2 and 85 information bytes
34064b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34074b6e228eSLuiz Augusto von Dentz 	 */
34084b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH1))
34094b6e228eSLuiz Augusto von Dentz 		chan->imtu = 83;
34104b6e228eSLuiz Augusto von Dentz 
34114b6e228eSLuiz Augusto von Dentz 	/* The 2-DH3 packet has between 2 and 369 information bytes
34124b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34134b6e228eSLuiz Augusto von Dentz 	 */
34144b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH3))
34154b6e228eSLuiz Augusto von Dentz 		chan->imtu = 367;
34164b6e228eSLuiz Augusto von Dentz 
34174b6e228eSLuiz Augusto von Dentz 	/* The 3-DH3 packet has between 2 and 554 information bytes
34184b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34194b6e228eSLuiz Augusto von Dentz 	 */
34204b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH3))
34214b6e228eSLuiz Augusto von Dentz 		chan->imtu = 552;
34224b6e228eSLuiz Augusto von Dentz 
34234b6e228eSLuiz Augusto von Dentz 	/* The 2-DH5 packet has between 2 and 681 information bytes
34244b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34254b6e228eSLuiz Augusto von Dentz 	 */
34264b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_2DH5))
34274b6e228eSLuiz Augusto von Dentz 		chan->imtu = 679;
34284b6e228eSLuiz Augusto von Dentz 
34294b6e228eSLuiz Augusto von Dentz 	/* The 3-DH5 packet has between 2 and 1023 information bytes
34304b6e228eSLuiz Augusto von Dentz 	 * (including the 2-byte payload header)
34314b6e228eSLuiz Augusto von Dentz 	 */
34324b6e228eSLuiz Augusto von Dentz 	if (!(conn->pkt_type & HCI_3DH5))
34334b6e228eSLuiz Augusto von Dentz 		chan->imtu = 1021;
34344b6e228eSLuiz Augusto von Dentz }
34354b6e228eSLuiz Augusto von Dentz 
3436e860d2c9SBen Seri static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
34370a708f8fSGustavo F. Padovan {
34380a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = data;
34390c1bc5c6SGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
34400a708f8fSGustavo F. Padovan 	void *ptr = req->data;
3441e860d2c9SBen Seri 	void *endptr = data + data_size;
3442c8f79162SAndrei Emeltchenko 	u16 size;
34430a708f8fSGustavo F. Padovan 
344449208c9cSGustavo F. Padovan 	BT_DBG("chan %p", chan);
34450a708f8fSGustavo F. Padovan 
344673ffa904SGustavo F. Padovan 	if (chan->num_conf_req || chan->num_conf_rsp)
34470a708f8fSGustavo F. Padovan 		goto done;
34480a708f8fSGustavo F. Padovan 
34490c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34500a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
34510a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3452c1360a1cSGustavo F. Padovan 		if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
34530a708f8fSGustavo F. Padovan 			break;
34540a708f8fSGustavo F. Padovan 
3455848566b3SMarcel Holtmann 		if (__l2cap_efs_supported(chan->conn))
3456f89cef09SAndrei Emeltchenko 			set_bit(FLAG_EFS_ENABLE, &chan->flags);
3457f89cef09SAndrei Emeltchenko 
345819186c7bSGustavo A. R. Silva 		fallthrough;
34590a708f8fSGustavo F. Padovan 	default:
34608c1d787bSGustavo F. Padovan 		chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
34610a708f8fSGustavo F. Padovan 		break;
34620a708f8fSGustavo F. Padovan 	}
34630a708f8fSGustavo F. Padovan 
34640a708f8fSGustavo F. Padovan done:
34654b6e228eSLuiz Augusto von Dentz 	if (chan->imtu != L2CAP_DEFAULT_MTU) {
34664b6e228eSLuiz Augusto von Dentz 		if (!chan->imtu)
34674b6e228eSLuiz Augusto von Dentz 			l2cap_mtu_auto(chan);
34684b6e228eSLuiz Augusto von Dentz 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
34694b6e228eSLuiz Augusto von Dentz 				   endptr - ptr);
34704b6e228eSLuiz Augusto von Dentz 	}
34710a708f8fSGustavo F. Padovan 
34720c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
34730a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
34746fea7ad1SMarcel Holtmann 		if (disable_ertm)
34756fea7ad1SMarcel Holtmann 			break;
34766fea7ad1SMarcel Holtmann 
34778c1d787bSGustavo F. Padovan 		if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
34788c1d787bSGustavo F. Padovan 		    !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
34790a708f8fSGustavo F. Padovan 			break;
34800a708f8fSGustavo F. Padovan 
34810a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_BASIC;
34820a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
34830a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
34840a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
34850a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
34860a708f8fSGustavo F. Padovan 		rfc.max_pdu_size    = 0;
34870a708f8fSGustavo F. Padovan 
34880a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3489e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
34900a708f8fSGustavo F. Padovan 		break;
34910a708f8fSGustavo F. Padovan 
34920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
34930a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_ERTM;
349447d1ec61SGustavo F. Padovan 		rfc.max_transmit    = chan->max_tx;
349536c86c85SMat Martineau 
349636c86c85SMat Martineau 		__l2cap_set_ertm_timeouts(chan, &rfc);
3497c8f79162SAndrei Emeltchenko 
3498c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
34992d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3500c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3501c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35020a708f8fSGustavo F. Padovan 
35036327eb98SAndrei Emeltchenko 		l2cap_txwin_setup(chan);
35046327eb98SAndrei Emeltchenko 
35056327eb98SAndrei Emeltchenko 		rfc.txwin_size = min_t(u16, chan->tx_win,
35066327eb98SAndrei Emeltchenko 				       L2CAP_DEFAULT_TX_WINDOW);
35070a708f8fSGustavo F. Padovan 
35080a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3509e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35100a708f8fSGustavo F. Padovan 
3511f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3512e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3513f89cef09SAndrei Emeltchenko 
35146327eb98SAndrei Emeltchenko 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
35156327eb98SAndrei Emeltchenko 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3516e860d2c9SBen Seri 					   chan->tx_win, endptr - ptr);
351760918918SAndrei Emeltchenko 
351860918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
351960918918SAndrei Emeltchenko 			if (chan->fcs == L2CAP_FCS_NONE ||
3520f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
352160918918SAndrei Emeltchenko 				chan->fcs = L2CAP_FCS_NONE;
352260918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3523e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
352460918918SAndrei Emeltchenko 			}
35250a708f8fSGustavo F. Padovan 		break;
35260a708f8fSGustavo F. Padovan 
35270a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
3528273759e2SMat Martineau 		l2cap_txwin_setup(chan);
35290a708f8fSGustavo F. Padovan 		rfc.mode            = L2CAP_MODE_STREAMING;
35300a708f8fSGustavo F. Padovan 		rfc.txwin_size      = 0;
35310a708f8fSGustavo F. Padovan 		rfc.max_transmit    = 0;
35320a708f8fSGustavo F. Padovan 		rfc.retrans_timeout = 0;
35330a708f8fSGustavo F. Padovan 		rfc.monitor_timeout = 0;
3534c8f79162SAndrei Emeltchenko 
3535c8f79162SAndrei Emeltchenko 		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
35362d792818SGustavo Padovan 			     L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE -
3537c8f79162SAndrei Emeltchenko 			     L2CAP_FCS_SIZE);
3538c8f79162SAndrei Emeltchenko 		rfc.max_pdu_size = cpu_to_le16(size);
35390a708f8fSGustavo F. Padovan 
35400a708f8fSGustavo F. Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3541e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
35420a708f8fSGustavo F. Padovan 
3543f89cef09SAndrei Emeltchenko 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3544e860d2c9SBen Seri 			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
3545f89cef09SAndrei Emeltchenko 
354660918918SAndrei Emeltchenko 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
354747d1ec61SGustavo F. Padovan 			if (chan->fcs == L2CAP_FCS_NONE ||
3548f2592d3eSAndrei Emeltchenko 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
354947d1ec61SGustavo F. Padovan 				chan->fcs = L2CAP_FCS_NONE;
355060918918SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3551e860d2c9SBen Seri 						   chan->fcs, endptr - ptr);
35520a708f8fSGustavo F. Padovan 			}
35530a708f8fSGustavo F. Padovan 		break;
35540a708f8fSGustavo F. Padovan 	}
35550a708f8fSGustavo F. Padovan 
3556fe4128e0SGustavo F. Padovan 	req->dcid  = cpu_to_le16(chan->dcid);
3557dcf4adbfSJoe Perches 	req->flags = cpu_to_le16(0);
35580a708f8fSGustavo F. Padovan 
35590a708f8fSGustavo F. Padovan 	return ptr - data;
35600a708f8fSGustavo F. Padovan }
35610a708f8fSGustavo F. Padovan 
3562e860d2c9SBen Seri static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
35630a708f8fSGustavo F. Padovan {
35640a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = data;
35650a708f8fSGustavo F. Padovan 	void *ptr = rsp->data;
3566e860d2c9SBen Seri 	void *endptr = data + data_size;
356773ffa904SGustavo F. Padovan 	void *req = chan->conf_req;
356873ffa904SGustavo F. Padovan 	int len = chan->conf_len;
35690a708f8fSGustavo F. Padovan 	int type, hint, olen;
35700a708f8fSGustavo F. Padovan 	unsigned long val;
35710a708f8fSGustavo F. Padovan 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
357242dceae2SAndrei Emeltchenko 	struct l2cap_conf_efs efs;
357342dceae2SAndrei Emeltchenko 	u8 remote_efs = 0;
35740a708f8fSGustavo F. Padovan 	u16 mtu = L2CAP_DEFAULT_MTU;
35750a708f8fSGustavo F. Padovan 	u16 result = L2CAP_CONF_SUCCESS;
3576c8f79162SAndrei Emeltchenko 	u16 size;
35770a708f8fSGustavo F. Padovan 
357873ffa904SGustavo F. Padovan 	BT_DBG("chan %p", chan);
35790a708f8fSGustavo F. Padovan 
35800a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
35810a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
35827c9cbd0bSMarcel Holtmann 		if (len < 0)
35837c9cbd0bSMarcel Holtmann 			break;
35840a708f8fSGustavo F. Padovan 
35850a708f8fSGustavo F. Padovan 		hint  = type & L2CAP_CONF_HINT;
35860a708f8fSGustavo F. Padovan 		type &= L2CAP_CONF_MASK;
35870a708f8fSGustavo F. Padovan 
35880a708f8fSGustavo F. Padovan 		switch (type) {
35890a708f8fSGustavo F. Padovan 		case L2CAP_CONF_MTU:
3590af3d5d1cSMarcel Holtmann 			if (olen != 2)
3591af3d5d1cSMarcel Holtmann 				break;
35920a708f8fSGustavo F. Padovan 			mtu = val;
35930a708f8fSGustavo F. Padovan 			break;
35940a708f8fSGustavo F. Padovan 
35950a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FLUSH_TO:
3596af3d5d1cSMarcel Holtmann 			if (olen != 2)
3597af3d5d1cSMarcel Holtmann 				break;
35980c1bc5c6SGustavo F. Padovan 			chan->flush_to = val;
35990a708f8fSGustavo F. Padovan 			break;
36000a708f8fSGustavo F. Padovan 
36010a708f8fSGustavo F. Padovan 		case L2CAP_CONF_QOS:
36020a708f8fSGustavo F. Padovan 			break;
36030a708f8fSGustavo F. Padovan 
36040a708f8fSGustavo F. Padovan 		case L2CAP_CONF_RFC:
3605af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
3606af3d5d1cSMarcel Holtmann 				break;
36070a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *) val, olen);
36080a708f8fSGustavo F. Padovan 			break;
36090a708f8fSGustavo F. Padovan 
36100a708f8fSGustavo F. Padovan 		case L2CAP_CONF_FCS:
3611af3d5d1cSMarcel Holtmann 			if (olen != 1)
3612af3d5d1cSMarcel Holtmann 				break;
36130a708f8fSGustavo F. Padovan 			if (val == L2CAP_FCS_NONE)
3614f2592d3eSAndrei Emeltchenko 				set_bit(CONF_RECV_NO_FCS, &chan->conf_state);
361542dceae2SAndrei Emeltchenko 			break;
36160a708f8fSGustavo F. Padovan 
361742dceae2SAndrei Emeltchenko 		case L2CAP_CONF_EFS:
3618af3d5d1cSMarcel Holtmann 			if (olen != sizeof(efs))
3619af3d5d1cSMarcel Holtmann 				break;
362042dceae2SAndrei Emeltchenko 			remote_efs = 1;
362142dceae2SAndrei Emeltchenko 			memcpy(&efs, (void *) val, olen);
36220a708f8fSGustavo F. Padovan 			break;
36230a708f8fSGustavo F. Padovan 
36246327eb98SAndrei Emeltchenko 		case L2CAP_CONF_EWS:
3625af3d5d1cSMarcel Holtmann 			if (olen != 2)
3626af3d5d1cSMarcel Holtmann 				break;
36270bd49fc7SJohan Hedberg 			if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
36286327eb98SAndrei Emeltchenko 				return -ECONNREFUSED;
36296327eb98SAndrei Emeltchenko 			set_bit(FLAG_EXT_CTRL, &chan->flags);
36306327eb98SAndrei Emeltchenko 			set_bit(CONF_EWS_RECV, &chan->conf_state);
3631836be934SAndrei Emeltchenko 			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
36326327eb98SAndrei Emeltchenko 			chan->remote_tx_win = val;
36330a708f8fSGustavo F. Padovan 			break;
36340a708f8fSGustavo F. Padovan 
36350a708f8fSGustavo F. Padovan 		default:
36360a708f8fSGustavo F. Padovan 			if (hint)
36370a708f8fSGustavo F. Padovan 				break;
36380a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNKNOWN;
36395b8ec15dSJimmy Wahlberg 			l2cap_add_conf_opt(&ptr, (u8)type, sizeof(u8), type, endptr - ptr);
36400a708f8fSGustavo F. Padovan 			break;
36410a708f8fSGustavo F. Padovan 		}
36420a708f8fSGustavo F. Padovan 	}
36430a708f8fSGustavo F. Padovan 
364473ffa904SGustavo F. Padovan 	if (chan->num_conf_rsp || chan->num_conf_req > 1)
36450a708f8fSGustavo F. Padovan 		goto done;
36460a708f8fSGustavo F. Padovan 
36470c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
36480a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
36490a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
3650c1360a1cSGustavo F. Padovan 		if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
36510c1bc5c6SGustavo F. Padovan 			chan->mode = l2cap_select_mode(rfc.mode,
36528c1d787bSGustavo F. Padovan 						       chan->conn->feat_mask);
36530a708f8fSGustavo F. Padovan 			break;
36540a708f8fSGustavo F. Padovan 		}
36550a708f8fSGustavo F. Padovan 
365642dceae2SAndrei Emeltchenko 		if (remote_efs) {
3657848566b3SMarcel Holtmann 			if (__l2cap_efs_supported(chan->conn))
365842dceae2SAndrei Emeltchenko 				set_bit(FLAG_EFS_ENABLE, &chan->flags);
365942dceae2SAndrei Emeltchenko 			else
366042dceae2SAndrei Emeltchenko 				return -ECONNREFUSED;
366142dceae2SAndrei Emeltchenko 		}
366242dceae2SAndrei Emeltchenko 
36630c1bc5c6SGustavo F. Padovan 		if (chan->mode != rfc.mode)
36640a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36650a708f8fSGustavo F. Padovan 
36660a708f8fSGustavo F. Padovan 		break;
36670a708f8fSGustavo F. Padovan 	}
36680a708f8fSGustavo F. Padovan 
36690a708f8fSGustavo F. Padovan done:
36700c1bc5c6SGustavo F. Padovan 	if (chan->mode != rfc.mode) {
36710a708f8fSGustavo F. Padovan 		result = L2CAP_CONF_UNACCEPT;
36720c1bc5c6SGustavo F. Padovan 		rfc.mode = chan->mode;
36730a708f8fSGustavo F. Padovan 
367473ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp == 1)
36750a708f8fSGustavo F. Padovan 			return -ECONNREFUSED;
36760a708f8fSGustavo F. Padovan 
36772d792818SGustavo Padovan 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3678e860d2c9SBen Seri 				   (unsigned long) &rfc, endptr - ptr);
36790a708f8fSGustavo F. Padovan 	}
36800a708f8fSGustavo F. Padovan 
36810a708f8fSGustavo F. Padovan 	if (result == L2CAP_CONF_SUCCESS) {
36820a708f8fSGustavo F. Padovan 		/* Configure output options and let the other side know
36830a708f8fSGustavo F. Padovan 		 * which ones we don't like. */
36840a708f8fSGustavo F. Padovan 
36850a708f8fSGustavo F. Padovan 		if (mtu < L2CAP_DEFAULT_MIN_MTU)
36860a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_UNACCEPT;
36870a708f8fSGustavo F. Padovan 		else {
36880c1bc5c6SGustavo F. Padovan 			chan->omtu = mtu;
3689c1360a1cSGustavo F. Padovan 			set_bit(CONF_MTU_DONE, &chan->conf_state);
36900a708f8fSGustavo F. Padovan 		}
3691e860d2c9SBen Seri 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
36920a708f8fSGustavo F. Padovan 
369342dceae2SAndrei Emeltchenko 		if (remote_efs) {
369442dceae2SAndrei Emeltchenko 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
369542dceae2SAndrei Emeltchenko 			    efs.stype != L2CAP_SERV_NOTRAFIC &&
369642dceae2SAndrei Emeltchenko 			    efs.stype != chan->local_stype) {
369742dceae2SAndrei Emeltchenko 
369842dceae2SAndrei Emeltchenko 				result = L2CAP_CONF_UNACCEPT;
369942dceae2SAndrei Emeltchenko 
370042dceae2SAndrei Emeltchenko 				if (chan->num_conf_req >= 1)
370142dceae2SAndrei Emeltchenko 					return -ECONNREFUSED;
370242dceae2SAndrei Emeltchenko 
370342dceae2SAndrei Emeltchenko 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
370442dceae2SAndrei Emeltchenko 						   sizeof(efs),
3705e860d2c9SBen Seri 						   (unsigned long) &efs, endptr - ptr);
37060e8b207eSAndrei Emeltchenko 			} else {
37073e6b3b95SGustavo F. Padovan 				/* Send PENDING Conf Rsp */
37080e8b207eSAndrei Emeltchenko 				result = L2CAP_CONF_PENDING;
37090e8b207eSAndrei Emeltchenko 				set_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
371042dceae2SAndrei Emeltchenko 			}
371142dceae2SAndrei Emeltchenko 		}
371242dceae2SAndrei Emeltchenko 
37130a708f8fSGustavo F. Padovan 		switch (rfc.mode) {
37140a708f8fSGustavo F. Padovan 		case L2CAP_MODE_BASIC:
371547d1ec61SGustavo F. Padovan 			chan->fcs = L2CAP_FCS_NONE;
3716c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37170a708f8fSGustavo F. Padovan 			break;
37180a708f8fSGustavo F. Padovan 
37190a708f8fSGustavo F. Padovan 		case L2CAP_MODE_ERTM:
37206327eb98SAndrei Emeltchenko 			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
37212c03a7a4SGustavo F. Padovan 				chan->remote_tx_win = rfc.txwin_size;
37226327eb98SAndrei Emeltchenko 			else
37236327eb98SAndrei Emeltchenko 				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
37246327eb98SAndrei Emeltchenko 
37252c03a7a4SGustavo F. Padovan 			chan->remote_max_tx = rfc.max_transmit;
37260a708f8fSGustavo F. Padovan 
3727c8f79162SAndrei Emeltchenko 			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
37282d792818SGustavo Padovan 				     chan->conn->mtu - L2CAP_EXT_HDR_SIZE -
37292d792818SGustavo Padovan 				     L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE);
3730c8f79162SAndrei Emeltchenko 			rfc.max_pdu_size = cpu_to_le16(size);
3731c8f79162SAndrei Emeltchenko 			chan->remote_mps = size;
37320a708f8fSGustavo F. Padovan 
373336c86c85SMat Martineau 			__l2cap_set_ertm_timeouts(chan, &rfc);
37340a708f8fSGustavo F. Padovan 
3735c1360a1cSGustavo F. Padovan 			set_bit(CONF_MODE_DONE, &chan->conf_state);
37360a708f8fSGustavo F. Padovan 
37370a708f8fSGustavo F. Padovan 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3738e860d2c9SBen Seri 					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
37390a708f8fSGustavo F. Padovan 
3740b1a2cd50SLuiz Augusto von Dentz 			if (remote_efs &&
3741b1a2cd50SLuiz Augusto von Dentz 			    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 
3938*9aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
393915f02b91SLuiz Augusto von Dentz {
3940*9aa9d947SLuiz Augusto von Dentz 	int *result = data;
394115f02b91SLuiz Augusto von Dentz 
3942*9aa9d947SLuiz Augusto von Dentz 	if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
394315f02b91SLuiz Augusto von Dentz 		return;
394415f02b91SLuiz Augusto von Dentz 
3945*9aa9d947SLuiz Augusto von Dentz 	switch (chan->state) {
3946*9aa9d947SLuiz Augusto von Dentz 	case BT_CONNECT2:
3947*9aa9d947SLuiz Augusto von Dentz 		/* If channel still pending accept add to result */
3948*9aa9d947SLuiz Augusto von Dentz 		(*result)++;
3949*9aa9d947SLuiz Augusto von Dentz 		return;
3950*9aa9d947SLuiz Augusto von Dentz 	case BT_CONNECTED:
3951*9aa9d947SLuiz Augusto von Dentz 		return;
3952*9aa9d947SLuiz Augusto von Dentz 	default:
3953*9aa9d947SLuiz Augusto von Dentz 		/* If not connected or pending accept it has been refused */
3954*9aa9d947SLuiz Augusto von Dentz 		*result = -ECONNREFUSED;
3955*9aa9d947SLuiz Augusto von Dentz 		return;
3956*9aa9d947SLuiz Augusto von Dentz 	}
3957*9aa9d947SLuiz Augusto von Dentz }
395815f02b91SLuiz Augusto von Dentz 
3959*9aa9d947SLuiz Augusto von Dentz struct l2cap_ecred_rsp_data {
3960*9aa9d947SLuiz Augusto von Dentz 	struct {
3961*9aa9d947SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
3962*9aa9d947SLuiz Augusto von Dentz 		__le16 scid[L2CAP_ECRED_MAX_CID];
3963*9aa9d947SLuiz Augusto von Dentz 	} __packed pdu;
3964*9aa9d947SLuiz Augusto von Dentz 	int count;
3965*9aa9d947SLuiz Augusto von Dentz };
396615f02b91SLuiz Augusto von Dentz 
3967*9aa9d947SLuiz Augusto von Dentz static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
3968*9aa9d947SLuiz Augusto von Dentz {
3969*9aa9d947SLuiz Augusto von Dentz 	struct l2cap_ecred_rsp_data *rsp = data;
397015f02b91SLuiz Augusto von Dentz 
3971*9aa9d947SLuiz Augusto von Dentz 	if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
3972*9aa9d947SLuiz Augusto von Dentz 		return;
397315f02b91SLuiz Augusto von Dentz 
397415f02b91SLuiz Augusto von Dentz 	/* Reset ident so only one response is sent */
397515f02b91SLuiz Augusto von Dentz 	chan->ident = 0;
397615f02b91SLuiz Augusto von Dentz 
397715f02b91SLuiz Augusto von Dentz 	/* Include all channels pending with the same ident */
3978*9aa9d947SLuiz Augusto von Dentz 	if (!rsp->pdu.rsp.result)
3979*9aa9d947SLuiz Augusto von Dentz 		rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
3980*9aa9d947SLuiz Augusto von Dentz 	else
3981*9aa9d947SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
398215f02b91SLuiz Augusto von Dentz }
398315f02b91SLuiz Augusto von Dentz 
3984*9aa9d947SLuiz Augusto von Dentz void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
3985*9aa9d947SLuiz Augusto von Dentz {
3986*9aa9d947SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
3987*9aa9d947SLuiz Augusto von Dentz 	struct l2cap_ecred_rsp_data data;
3988*9aa9d947SLuiz Augusto von Dentz 	u16 id = chan->ident;
3989*9aa9d947SLuiz Augusto von Dentz 	int result = 0;
399015f02b91SLuiz Augusto von Dentz 
3991*9aa9d947SLuiz Augusto von Dentz 	if (!id)
3992*9aa9d947SLuiz Augusto von Dentz 		return;
3993*9aa9d947SLuiz Augusto von Dentz 
3994*9aa9d947SLuiz Augusto von Dentz 	BT_DBG("chan %p id %d", chan, id);
3995*9aa9d947SLuiz Augusto von Dentz 
3996*9aa9d947SLuiz Augusto von Dentz 	memset(&data, 0, sizeof(data));
3997*9aa9d947SLuiz Augusto von Dentz 
3998*9aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
3999*9aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.mps     = cpu_to_le16(chan->mps);
4000*9aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
4001*9aa9d947SLuiz Augusto von Dentz 	data.pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
4002*9aa9d947SLuiz Augusto von Dentz 
4003*9aa9d947SLuiz Augusto von Dentz 	/* Verify that all channels are ready */
4004*9aa9d947SLuiz Augusto von Dentz 	__l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
4005*9aa9d947SLuiz Augusto von Dentz 
4006*9aa9d947SLuiz Augusto von Dentz 	if (result > 0)
4007*9aa9d947SLuiz Augusto von Dentz 		return;
4008*9aa9d947SLuiz Augusto von Dentz 
4009*9aa9d947SLuiz Augusto von Dentz 	if (result < 0)
4010*9aa9d947SLuiz Augusto von Dentz 		data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
4011*9aa9d947SLuiz Augusto von Dentz 
4012*9aa9d947SLuiz Augusto von Dentz 	/* Build response */
4013*9aa9d947SLuiz Augusto von Dentz 	__l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
4014*9aa9d947SLuiz Augusto von Dentz 
4015*9aa9d947SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
4016*9aa9d947SLuiz Augusto von Dentz 		       sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
4017*9aa9d947SLuiz Augusto von Dentz 		       &data.pdu);
401815f02b91SLuiz Augusto von Dentz }
401915f02b91SLuiz Augusto von Dentz 
40208c1d787bSGustavo F. Padovan void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
4021710f9b0aSGustavo F. Padovan {
4022710f9b0aSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
40238c1d787bSGustavo F. Padovan 	struct l2cap_conn *conn = chan->conn;
4024710f9b0aSGustavo F. Padovan 	u8 buf[128];
4025439f34acSAndrei Emeltchenko 	u8 rsp_code;
4026710f9b0aSGustavo F. Padovan 
4027fe4128e0SGustavo F. Padovan 	rsp.scid   = cpu_to_le16(chan->dcid);
4028fe4128e0SGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(chan->scid);
4029dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
4030dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4031439f34acSAndrei Emeltchenko 
4032439f34acSAndrei Emeltchenko 	if (chan->hs_hcon)
4033439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CREATE_CHAN_RSP;
4034439f34acSAndrei Emeltchenko 	else
4035439f34acSAndrei Emeltchenko 		rsp_code = L2CAP_CONN_RSP;
4036439f34acSAndrei Emeltchenko 
4037439f34acSAndrei Emeltchenko 	BT_DBG("chan %p rsp_code %u", chan, rsp_code);
4038439f34acSAndrei Emeltchenko 
4039439f34acSAndrei Emeltchenko 	l2cap_send_cmd(conn, chan->ident, rsp_code, sizeof(rsp), &rsp);
4040710f9b0aSGustavo F. Padovan 
4041c1360a1cSGustavo F. Padovan 	if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
4042710f9b0aSGustavo F. Padovan 		return;
4043710f9b0aSGustavo F. Padovan 
4044710f9b0aSGustavo F. Padovan 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4045e860d2c9SBen Seri 		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
4046710f9b0aSGustavo F. Padovan 	chan->num_conf_req++;
4047710f9b0aSGustavo F. Padovan }
4048710f9b0aSGustavo F. Padovan 
404947d1ec61SGustavo F. Padovan static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
40500a708f8fSGustavo F. Padovan {
40510a708f8fSGustavo F. Padovan 	int type, olen;
40520a708f8fSGustavo F. Padovan 	unsigned long val;
4053c20f8e35SMat Martineau 	/* Use sane default values in case a misbehaving remote device
4054c20f8e35SMat Martineau 	 * did not send an RFC or extended window size option.
4055c20f8e35SMat Martineau 	 */
4056c20f8e35SMat Martineau 	u16 txwin_ext = chan->ack_win;
4057c20f8e35SMat Martineau 	struct l2cap_conf_rfc rfc = {
4058c20f8e35SMat Martineau 		.mode = chan->mode,
4059dcf4adbfSJoe Perches 		.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO),
4060dcf4adbfSJoe Perches 		.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO),
4061c20f8e35SMat Martineau 		.max_pdu_size = cpu_to_le16(chan->imtu),
4062c20f8e35SMat Martineau 		.txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW),
4063c20f8e35SMat Martineau 	};
40640a708f8fSGustavo F. Padovan 
406547d1ec61SGustavo F. Padovan 	BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
40660a708f8fSGustavo F. Padovan 
40670c1bc5c6SGustavo F. Padovan 	if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
40680a708f8fSGustavo F. Padovan 		return;
40690a708f8fSGustavo F. Padovan 
40700a708f8fSGustavo F. Padovan 	while (len >= L2CAP_CONF_OPT_SIZE) {
40710a708f8fSGustavo F. Padovan 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
40727c9cbd0bSMarcel Holtmann 		if (len < 0)
40737c9cbd0bSMarcel Holtmann 			break;
40740a708f8fSGustavo F. Padovan 
4075c20f8e35SMat Martineau 		switch (type) {
4076c20f8e35SMat Martineau 		case L2CAP_CONF_RFC:
4077af3d5d1cSMarcel Holtmann 			if (olen != sizeof(rfc))
4078af3d5d1cSMarcel Holtmann 				break;
40790a708f8fSGustavo F. Padovan 			memcpy(&rfc, (void *)val, olen);
4080c20f8e35SMat Martineau 			break;
4081c20f8e35SMat Martineau 		case L2CAP_CONF_EWS:
4082af3d5d1cSMarcel Holtmann 			if (olen != 2)
4083af3d5d1cSMarcel Holtmann 				break;
4084c20f8e35SMat Martineau 			txwin_ext = val;
4085c20f8e35SMat Martineau 			break;
4086c20f8e35SMat Martineau 		}
40870a708f8fSGustavo F. Padovan 	}
40880a708f8fSGustavo F. Padovan 
40890a708f8fSGustavo F. Padovan 	switch (rfc.mode) {
40900a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
409147d1ec61SGustavo F. Padovan 		chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
409247d1ec61SGustavo F. Padovan 		chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
409347d1ec61SGustavo F. Padovan 		chan->mps = le16_to_cpu(rfc.max_pdu_size);
4094c20f8e35SMat Martineau 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
4095c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win, txwin_ext);
4096c20f8e35SMat Martineau 		else
4097c20f8e35SMat Martineau 			chan->ack_win = min_t(u16, chan->ack_win,
4098c20f8e35SMat Martineau 					      rfc.txwin_size);
40990a708f8fSGustavo F. Padovan 		break;
41000a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
410147d1ec61SGustavo F. Padovan 		chan->mps    = le16_to_cpu(rfc.max_pdu_size);
41020a708f8fSGustavo F. Padovan 	}
41030a708f8fSGustavo F. Padovan }
41040a708f8fSGustavo F. Padovan 
41052d792818SGustavo Padovan static inline int l2cap_command_rej(struct l2cap_conn *conn,
4106cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4107cb3b3152SJohan Hedberg 				    u8 *data)
41080a708f8fSGustavo F. Padovan {
4109e2fd318eSIlia Kolomisnky 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
41100a708f8fSGustavo F. Padovan 
4111cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rej))
4112cb3b3152SJohan Hedberg 		return -EPROTO;
4113cb3b3152SJohan Hedberg 
4114e2fd318eSIlia Kolomisnky 	if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
41150a708f8fSGustavo F. Padovan 		return 0;
41160a708f8fSGustavo F. Padovan 
41170a708f8fSGustavo F. Padovan 	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
41180a708f8fSGustavo F. Padovan 	    cmd->ident == conn->info_ident) {
411917cd3f37SUlisses Furquim 		cancel_delayed_work(&conn->info_timer);
41200a708f8fSGustavo F. Padovan 
41210a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
41220a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
41230a708f8fSGustavo F. Padovan 
41240a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
41250a708f8fSGustavo F. Padovan 	}
41260a708f8fSGustavo F. Padovan 
41270a708f8fSGustavo F. Padovan 	return 0;
41280a708f8fSGustavo F. Padovan }
41290a708f8fSGustavo F. Padovan 
41301700915fSMat Martineau static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
41311700915fSMat Martineau 					struct l2cap_cmd_hdr *cmd,
41324c89b6aaSMat Martineau 					u8 *data, u8 rsp_code, u8 amp_id)
41330a708f8fSGustavo F. Padovan {
41340a708f8fSGustavo F. Padovan 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
41350a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp rsp;
413623691d75SGustavo F. Padovan 	struct l2cap_chan *chan = NULL, *pchan;
41370a708f8fSGustavo F. Padovan 	int result, status = L2CAP_CS_NO_INFO;
41380a708f8fSGustavo F. Padovan 
41390a708f8fSGustavo F. Padovan 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
41400a708f8fSGustavo F. Padovan 	__le16 psm = req->psm;
41410a708f8fSGustavo F. Padovan 
4142097db76cSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid);
41430a708f8fSGustavo F. Padovan 
41440a708f8fSGustavo F. Padovan 	/* Check if we have socket listening on psm */
41456f59b904SMarcel Holtmann 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
4146bf20fd4eSJohan Hedberg 					 &conn->hcon->dst, ACL_LINK);
414723691d75SGustavo F. Padovan 	if (!pchan) {
41480a708f8fSGustavo F. Padovan 		result = L2CAP_CR_BAD_PSM;
41490a708f8fSGustavo F. Padovan 		goto sendresp;
41500a708f8fSGustavo F. Padovan 	}
41510a708f8fSGustavo F. Padovan 
41523df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
41538ffb9290SGustavo Padovan 	l2cap_chan_lock(pchan);
41540a708f8fSGustavo F. Padovan 
41550a708f8fSGustavo F. Padovan 	/* Check if the ACL is secure enough (if not SDP) */
4156dcf4adbfSJoe Perches 	if (psm != cpu_to_le16(L2CAP_PSM_SDP) &&
41570a708f8fSGustavo F. Padovan 	    !hci_conn_check_link_mode(conn->hcon)) {
41589f5a0d7bSAndrei Emeltchenko 		conn->disc_reason = HCI_ERROR_AUTH_FAILURE;
41590a708f8fSGustavo F. Padovan 		result = L2CAP_CR_SEC_BLOCK;
41600a708f8fSGustavo F. Padovan 		goto response;
41610a708f8fSGustavo F. Padovan 	}
41620a708f8fSGustavo F. Padovan 
41630a708f8fSGustavo F. Padovan 	result = L2CAP_CR_NO_MEM;
41640a708f8fSGustavo F. Padovan 
4165dd1a8f8aSMallikarjun Phulari 	/* Check for valid dynamic CID range (as per Erratum 3253) */
4166dd1a8f8aSMallikarjun Phulari 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_DYN_END) {
4167dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_INVALID_SCID;
41682dfa1003SGustavo Padovan 		goto response;
4169dd1a8f8aSMallikarjun Phulari 	}
4170dd1a8f8aSMallikarjun Phulari 
4171dd1a8f8aSMallikarjun Phulari 	/* Check if we already have channel with that dcid */
4172dd1a8f8aSMallikarjun Phulari 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
4173dd1a8f8aSMallikarjun Phulari 		result = L2CAP_CR_SCID_IN_USE;
4174dd1a8f8aSMallikarjun Phulari 		goto response;
4175dd1a8f8aSMallikarjun Phulari 	}
41762dfa1003SGustavo Padovan 
417780b98027SGustavo Padovan 	chan = pchan->ops->new_connection(pchan);
417880808e43SGustavo F. Padovan 	if (!chan)
41790a708f8fSGustavo F. Padovan 		goto response;
41800a708f8fSGustavo F. Padovan 
4181330b6c15SSyam Sidhardhan 	/* For certain devices (ex: HID mouse), support for authentication,
4182330b6c15SSyam Sidhardhan 	 * pairing and bonding is optional. For such devices, inorder to avoid
4183330b6c15SSyam Sidhardhan 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
4184330b6c15SSyam Sidhardhan 	 * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
4185330b6c15SSyam Sidhardhan 	 */
4186330b6c15SSyam Sidhardhan 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
4187330b6c15SSyam Sidhardhan 
41887eafc59eSMarcel Holtmann 	bacpy(&chan->src, &conn->hcon->src);
41897eafc59eSMarcel Holtmann 	bacpy(&chan->dst, &conn->hcon->dst);
4190a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
4191a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
4192fe4128e0SGustavo F. Padovan 	chan->psm  = psm;
4193fe4128e0SGustavo F. Padovan 	chan->dcid = scid;
41941700915fSMat Martineau 	chan->local_amp_id = amp_id;
41950a708f8fSGustavo F. Padovan 
41966be36555SAndrei Emeltchenko 	__l2cap_chan_add(conn, chan);
419748454079SGustavo F. Padovan 
4198fe4128e0SGustavo F. Padovan 	dcid = chan->scid;
41990a708f8fSGustavo F. Padovan 
42008d836d71SGustavo Padovan 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
42010a708f8fSGustavo F. Padovan 
4202fc7f8a7eSGustavo F. Padovan 	chan->ident = cmd->ident;
42030a708f8fSGustavo F. Padovan 
42040a708f8fSGustavo F. Padovan 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
4205e7cafc45SJohan Hedberg 		if (l2cap_chan_check_security(chan, false)) {
4206bdc25783SMarcel Holtmann 			if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
4207f93fa273SGustavo Padovan 				l2cap_state_change(chan, BT_CONNECT2);
42080a708f8fSGustavo F. Padovan 				result = L2CAP_CR_PEND;
42090a708f8fSGustavo F. Padovan 				status = L2CAP_CS_AUTHOR_PEND;
42102dc4e510SGustavo Padovan 				chan->ops->defer(chan);
42110a708f8fSGustavo F. Padovan 			} else {
42121700915fSMat Martineau 				/* Force pending result for AMP controllers.
42131700915fSMat Martineau 				 * The connection will succeed after the
42141700915fSMat Martineau 				 * physical link is up.
42151700915fSMat Martineau 				 */
42166ed971caSMarcel Holtmann 				if (amp_id == AMP_ID_BREDR) {
4217f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
42180a708f8fSGustavo F. Padovan 					result = L2CAP_CR_SUCCESS;
42196ed971caSMarcel Holtmann 				} else {
4220f93fa273SGustavo Padovan 					l2cap_state_change(chan, BT_CONNECT2);
42216ed971caSMarcel Holtmann 					result = L2CAP_CR_PEND;
42221700915fSMat Martineau 				}
42230a708f8fSGustavo F. Padovan 				status = L2CAP_CS_NO_INFO;
42240a708f8fSGustavo F. Padovan 			}
42250a708f8fSGustavo F. Padovan 		} else {
4226f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONNECT2);
42270a708f8fSGustavo F. Padovan 			result = L2CAP_CR_PEND;
42280a708f8fSGustavo F. Padovan 			status = L2CAP_CS_AUTHEN_PEND;
42290a708f8fSGustavo F. Padovan 		}
42300a708f8fSGustavo F. Padovan 	} else {
4231f93fa273SGustavo Padovan 		l2cap_state_change(chan, BT_CONNECT2);
42320a708f8fSGustavo F. Padovan 		result = L2CAP_CR_PEND;
42330a708f8fSGustavo F. Padovan 		status = L2CAP_CS_NO_INFO;
42340a708f8fSGustavo F. Padovan 	}
42350a708f8fSGustavo F. Padovan 
42360a708f8fSGustavo F. Padovan response:
42378ffb9290SGustavo Padovan 	l2cap_chan_unlock(pchan);
42383df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
4239a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
42400a708f8fSGustavo F. Padovan 
42410a708f8fSGustavo F. Padovan sendresp:
42420a708f8fSGustavo F. Padovan 	rsp.scid   = cpu_to_le16(scid);
42430a708f8fSGustavo F. Padovan 	rsp.dcid   = cpu_to_le16(dcid);
42440a708f8fSGustavo F. Padovan 	rsp.result = cpu_to_le16(result);
42450a708f8fSGustavo F. Padovan 	rsp.status = cpu_to_le16(status);
42464c89b6aaSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
42470a708f8fSGustavo F. Padovan 
42480a708f8fSGustavo F. Padovan 	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
42490a708f8fSGustavo F. Padovan 		struct l2cap_info_req info;
4250dcf4adbfSJoe Perches 		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
42510a708f8fSGustavo F. Padovan 
42520a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
42530a708f8fSGustavo F. Padovan 		conn->info_ident = l2cap_get_ident(conn);
42540a708f8fSGustavo F. Padovan 
4255ba13ccd9SMarcel Holtmann 		schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT);
42560a708f8fSGustavo F. Padovan 
42572d792818SGustavo Padovan 		l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ,
42582d792818SGustavo Padovan 			       sizeof(info), &info);
42590a708f8fSGustavo F. Padovan 	}
42600a708f8fSGustavo F. Padovan 
4261c1360a1cSGustavo F. Padovan 	if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
42620a708f8fSGustavo F. Padovan 	    result == L2CAP_CR_SUCCESS) {
42630a708f8fSGustavo F. Padovan 		u8 buf[128];
4264c1360a1cSGustavo F. Padovan 		set_bit(CONF_REQ_SENT, &chan->conf_state);
42650a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4266e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
426773ffa904SGustavo F. Padovan 		chan->num_conf_req++;
42680a708f8fSGustavo F. Padovan 	}
42691700915fSMat Martineau 
42701700915fSMat Martineau 	return chan;
42714c89b6aaSMat Martineau }
42720a708f8fSGustavo F. Padovan 
42734c89b6aaSMat Martineau static int l2cap_connect_req(struct l2cap_conn *conn,
4274cb3b3152SJohan Hedberg 			     struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
42754c89b6aaSMat Martineau {
42767b064edaSJaganath Kanakkassery 	struct hci_dev *hdev = conn->hcon->hdev;
42777b064edaSJaganath Kanakkassery 	struct hci_conn *hcon = conn->hcon;
42787b064edaSJaganath Kanakkassery 
4279cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(struct l2cap_conn_req))
4280cb3b3152SJohan Hedberg 		return -EPROTO;
4281cb3b3152SJohan Hedberg 
42827b064edaSJaganath Kanakkassery 	hci_dev_lock(hdev);
4283d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hdev, HCI_MGMT) &&
42847b064edaSJaganath Kanakkassery 	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
42851c6ed31bSYu Liu 		mgmt_device_connected(hdev, hcon, NULL, 0);
42867b064edaSJaganath Kanakkassery 	hci_dev_unlock(hdev);
42877b064edaSJaganath Kanakkassery 
4288300229f9SGustavo Padovan 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
42890a708f8fSGustavo F. Padovan 	return 0;
42900a708f8fSGustavo F. Padovan }
42910a708f8fSGustavo F. Padovan 
42925909cf30SMat Martineau static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
4293cb3b3152SJohan Hedberg 				    struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4294cb3b3152SJohan Hedberg 				    u8 *data)
42950a708f8fSGustavo F. Padovan {
42960a708f8fSGustavo F. Padovan 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
42970a708f8fSGustavo F. Padovan 	u16 scid, dcid, result, status;
429848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
42990a708f8fSGustavo F. Padovan 	u8 req[128];
43003df91ea2SAndrei Emeltchenko 	int err;
43010a708f8fSGustavo F. Padovan 
4302cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4303cb3b3152SJohan Hedberg 		return -EPROTO;
4304cb3b3152SJohan Hedberg 
43050a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
43060a708f8fSGustavo F. Padovan 	dcid   = __le16_to_cpu(rsp->dcid);
43070a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
43080a708f8fSGustavo F. Padovan 	status = __le16_to_cpu(rsp->status);
43090a708f8fSGustavo F. Padovan 
43101b009c98SAndrei Emeltchenko 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x",
43111b009c98SAndrei Emeltchenko 	       dcid, scid, result, status);
43120a708f8fSGustavo F. Padovan 
43133df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
43143df91ea2SAndrei Emeltchenko 
43150a708f8fSGustavo F. Padovan 	if (scid) {
43163df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_scid(conn, scid);
43173df91ea2SAndrei Emeltchenko 		if (!chan) {
431821870b52SJohan Hedberg 			err = -EBADSLT;
43193df91ea2SAndrei Emeltchenko 			goto unlock;
43203df91ea2SAndrei Emeltchenko 		}
43210a708f8fSGustavo F. Padovan 	} else {
43223df91ea2SAndrei Emeltchenko 		chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
43233df91ea2SAndrei Emeltchenko 		if (!chan) {
432421870b52SJohan Hedberg 			err = -EBADSLT;
43253df91ea2SAndrei Emeltchenko 			goto unlock;
43263df91ea2SAndrei Emeltchenko 		}
43270a708f8fSGustavo F. Padovan 	}
43280a708f8fSGustavo F. Padovan 
432935fcbc42SLuiz Augusto von Dentz 	chan = l2cap_chan_hold_unless_zero(chan);
433035fcbc42SLuiz Augusto von Dentz 	if (!chan) {
433135fcbc42SLuiz Augusto von Dentz 		err = -EBADSLT;
433235fcbc42SLuiz Augusto von Dentz 		goto unlock;
433335fcbc42SLuiz Augusto von Dentz 	}
433435fcbc42SLuiz Augusto von Dentz 
43353df91ea2SAndrei Emeltchenko 	err = 0;
43363df91ea2SAndrei Emeltchenko 
43376be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
433848454079SGustavo F. Padovan 
43390a708f8fSGustavo F. Padovan 	switch (result) {
43400a708f8fSGustavo F. Padovan 	case L2CAP_CR_SUCCESS:
434189bc500eSGustavo F. Padovan 		l2cap_state_change(chan, BT_CONFIG);
4342fc7f8a7eSGustavo F. Padovan 		chan->ident = 0;
4343fe4128e0SGustavo F. Padovan 		chan->dcid = dcid;
4344c1360a1cSGustavo F. Padovan 		clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
43450a708f8fSGustavo F. Padovan 
4346c1360a1cSGustavo F. Padovan 		if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
43470a708f8fSGustavo F. Padovan 			break;
43480a708f8fSGustavo F. Padovan 
43490a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4350e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
435173ffa904SGustavo F. Padovan 		chan->num_conf_req++;
43520a708f8fSGustavo F. Padovan 		break;
43530a708f8fSGustavo F. Padovan 
43540a708f8fSGustavo F. Padovan 	case L2CAP_CR_PEND:
4355c1360a1cSGustavo F. Padovan 		set_bit(CONF_CONNECT_PEND, &chan->conf_state);
43560a708f8fSGustavo F. Padovan 		break;
43570a708f8fSGustavo F. Padovan 
43580a708f8fSGustavo F. Padovan 	default:
435948454079SGustavo F. Padovan 		l2cap_chan_del(chan, ECONNREFUSED);
43600a708f8fSGustavo F. Padovan 		break;
43610a708f8fSGustavo F. Padovan 	}
43620a708f8fSGustavo F. Padovan 
43636be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
436435fcbc42SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
43653df91ea2SAndrei Emeltchenko 
43663df91ea2SAndrei Emeltchenko unlock:
43673df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
43683df91ea2SAndrei Emeltchenko 
43693df91ea2SAndrei Emeltchenko 	return err;
43700a708f8fSGustavo F. Padovan }
43710a708f8fSGustavo F. Padovan 
437247d1ec61SGustavo F. Padovan static inline void set_default_fcs(struct l2cap_chan *chan)
43730a708f8fSGustavo F. Padovan {
43740a708f8fSGustavo F. Padovan 	/* FCS is enabled only in ERTM or streaming mode, if one or both
43750a708f8fSGustavo F. Padovan 	 * sides request it.
43760a708f8fSGustavo F. Padovan 	 */
43770c1bc5c6SGustavo F. Padovan 	if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
437847d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_NONE;
4379f2592d3eSAndrei Emeltchenko 	else if (!test_bit(CONF_RECV_NO_FCS, &chan->conf_state))
438047d1ec61SGustavo F. Padovan 		chan->fcs = L2CAP_FCS_CRC16;
43810a708f8fSGustavo F. Padovan }
43820a708f8fSGustavo F. Padovan 
438329d8a590SAndrei Emeltchenko static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
438429d8a590SAndrei Emeltchenko 				    u8 ident, u16 flags)
438529d8a590SAndrei Emeltchenko {
438629d8a590SAndrei Emeltchenko 	struct l2cap_conn *conn = chan->conn;
438729d8a590SAndrei Emeltchenko 
438829d8a590SAndrei Emeltchenko 	BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident,
438929d8a590SAndrei Emeltchenko 	       flags);
439029d8a590SAndrei Emeltchenko 
439129d8a590SAndrei Emeltchenko 	clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state);
439229d8a590SAndrei Emeltchenko 	set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
439329d8a590SAndrei Emeltchenko 
439429d8a590SAndrei Emeltchenko 	l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP,
439529d8a590SAndrei Emeltchenko 		       l2cap_build_conf_rsp(chan, data,
439629d8a590SAndrei Emeltchenko 					    L2CAP_CONF_SUCCESS, flags), data);
439729d8a590SAndrei Emeltchenko }
439829d8a590SAndrei Emeltchenko 
4399662d652dSJohan Hedberg static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
4400662d652dSJohan Hedberg 				   u16 scid, u16 dcid)
4401662d652dSJohan Hedberg {
4402662d652dSJohan Hedberg 	struct l2cap_cmd_rej_cid rej;
4403662d652dSJohan Hedberg 
4404dcf4adbfSJoe Perches 	rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID);
4405662d652dSJohan Hedberg 	rej.scid = __cpu_to_le16(scid);
4406662d652dSJohan Hedberg 	rej.dcid = __cpu_to_le16(dcid);
4407662d652dSJohan Hedberg 
4408662d652dSJohan Hedberg 	l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
4409662d652dSJohan Hedberg }
4410662d652dSJohan Hedberg 
44112d792818SGustavo Padovan static inline int l2cap_config_req(struct l2cap_conn *conn,
44122d792818SGustavo Padovan 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
44132d792818SGustavo Padovan 				   u8 *data)
44140a708f8fSGustavo F. Padovan {
44150a708f8fSGustavo F. Padovan 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
44160a708f8fSGustavo F. Padovan 	u16 dcid, flags;
44170a708f8fSGustavo F. Padovan 	u8 rsp[64];
441848454079SGustavo F. Padovan 	struct l2cap_chan *chan;
44193c588192SMat Martineau 	int len, err = 0;
44200a708f8fSGustavo F. Padovan 
4421cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*req))
4422cb3b3152SJohan Hedberg 		return -EPROTO;
4423cb3b3152SJohan Hedberg 
44240a708f8fSGustavo F. Padovan 	dcid  = __le16_to_cpu(req->dcid);
44250a708f8fSGustavo F. Padovan 	flags = __le16_to_cpu(req->flags);
44260a708f8fSGustavo F. Padovan 
44270a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
44280a708f8fSGustavo F. Padovan 
4429baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, dcid);
4430662d652dSJohan Hedberg 	if (!chan) {
4431662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
4432662d652dSJohan Hedberg 		return 0;
4433662d652dSJohan Hedberg 	}
44340a708f8fSGustavo F. Padovan 
443596298f64SHoward Chung 	if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 &&
443696298f64SHoward Chung 	    chan->state != BT_CONNECTED) {
4437662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4438662d652dSJohan Hedberg 				       chan->dcid);
44390a708f8fSGustavo F. Padovan 		goto unlock;
44400a708f8fSGustavo F. Padovan 	}
44410a708f8fSGustavo F. Padovan 
44420a708f8fSGustavo F. Padovan 	/* Reject if config buffer is too small. */
44430a708f8fSGustavo F. Padovan 	len = cmd_len - sizeof(*req);
4444cb3b3152SJohan Hedberg 	if (chan->conf_len + len > sizeof(chan->conf_req)) {
44450a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4446fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
44470a708f8fSGustavo F. Padovan 			       L2CAP_CONF_REJECT, flags), rsp);
44480a708f8fSGustavo F. Padovan 		goto unlock;
44490a708f8fSGustavo F. Padovan 	}
44500a708f8fSGustavo F. Padovan 
44510a708f8fSGustavo F. Padovan 	/* Store config. */
445273ffa904SGustavo F. Padovan 	memcpy(chan->conf_req + chan->conf_len, req->data, len);
445373ffa904SGustavo F. Padovan 	chan->conf_len += len;
44540a708f8fSGustavo F. Padovan 
445559e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION) {
44560a708f8fSGustavo F. Padovan 		/* Incomplete config. Send empty response. */
44570a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
4458fe4128e0SGustavo F. Padovan 			       l2cap_build_conf_rsp(chan, rsp,
44595325e5bbSAndrei Emeltchenko 			       L2CAP_CONF_SUCCESS, flags), rsp);
44600a708f8fSGustavo F. Padovan 		goto unlock;
44610a708f8fSGustavo F. Padovan 	}
44620a708f8fSGustavo F. Padovan 
44630a708f8fSGustavo F. Padovan 	/* Complete config. */
4464e860d2c9SBen Seri 	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
44650a708f8fSGustavo F. Padovan 	if (len < 0) {
44665e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
44670a708f8fSGustavo F. Padovan 		goto unlock;
44680a708f8fSGustavo F. Padovan 	}
44690a708f8fSGustavo F. Padovan 
44701500109bSMat Martineau 	chan->ident = cmd->ident;
44710a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
4472bcd70260SSungwoo Kim 	if (chan->num_conf_rsp < L2CAP_CONF_MAX_CONF_RSP)
447373ffa904SGustavo F. Padovan 		chan->num_conf_rsp++;
44740a708f8fSGustavo F. Padovan 
44750a708f8fSGustavo F. Padovan 	/* Reset config buffer. */
447673ffa904SGustavo F. Padovan 	chan->conf_len = 0;
44770a708f8fSGustavo F. Padovan 
4478c1360a1cSGustavo F. Padovan 	if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
44790a708f8fSGustavo F. Padovan 		goto unlock;
44800a708f8fSGustavo F. Padovan 
4481c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
448247d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
44830a708f8fSGustavo F. Padovan 
4484105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4485105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
44863c588192SMat Martineau 			err = l2cap_ertm_init(chan);
44870a708f8fSGustavo F. Padovan 
44883c588192SMat Martineau 		if (err < 0)
44895e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
44903c588192SMat Martineau 		else
4491cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
44923c588192SMat Martineau 
44930a708f8fSGustavo F. Padovan 		goto unlock;
44940a708f8fSGustavo F. Padovan 	}
44950a708f8fSGustavo F. Padovan 
4496c1360a1cSGustavo F. Padovan 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
44970a708f8fSGustavo F. Padovan 		u8 buf[64];
44980a708f8fSGustavo F. Padovan 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4499e860d2c9SBen Seri 			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
450073ffa904SGustavo F. Padovan 		chan->num_conf_req++;
45010a708f8fSGustavo F. Padovan 	}
45020a708f8fSGustavo F. Padovan 
450349c922bbSStephen Hemminger 	/* Got Conf Rsp PENDING from remote side and assume we sent
45040e8b207eSAndrei Emeltchenko 	   Conf Rsp PENDING in the code above */
45050e8b207eSAndrei Emeltchenko 	if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
45060e8b207eSAndrei Emeltchenko 	    test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
45070e8b207eSAndrei Emeltchenko 
45080e8b207eSAndrei Emeltchenko 		/* check compatibility */
45090e8b207eSAndrei Emeltchenko 
451079de886dSAndrei Emeltchenko 		/* Send rsp for BR/EDR channel */
4511f351bc72SAndrei Emeltchenko 		if (!chan->hs_hcon)
451229d8a590SAndrei Emeltchenko 			l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
451379de886dSAndrei Emeltchenko 		else
451479de886dSAndrei Emeltchenko 			chan->ident = cmd->ident;
45150e8b207eSAndrei Emeltchenko 	}
45160e8b207eSAndrei Emeltchenko 
45170a708f8fSGustavo F. Padovan unlock:
45186be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
4519d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
45203c588192SMat Martineau 	return err;
45210a708f8fSGustavo F. Padovan }
45220a708f8fSGustavo F. Padovan 
45232d792818SGustavo Padovan static inline int l2cap_config_rsp(struct l2cap_conn *conn,
4524cb3b3152SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4525cb3b3152SJohan Hedberg 				   u8 *data)
45260a708f8fSGustavo F. Padovan {
45270a708f8fSGustavo F. Padovan 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
45280a708f8fSGustavo F. Padovan 	u16 scid, flags, result;
452948454079SGustavo F. Padovan 	struct l2cap_chan *chan;
4530cb3b3152SJohan Hedberg 	int len = cmd_len - sizeof(*rsp);
45313c588192SMat Martineau 	int err = 0;
45320a708f8fSGustavo F. Padovan 
4533cb3b3152SJohan Hedberg 	if (cmd_len < sizeof(*rsp))
4534cb3b3152SJohan Hedberg 		return -EPROTO;
4535cb3b3152SJohan Hedberg 
45360a708f8fSGustavo F. Padovan 	scid   = __le16_to_cpu(rsp->scid);
45370a708f8fSGustavo F. Padovan 	flags  = __le16_to_cpu(rsp->flags);
45380a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
45390a708f8fSGustavo F. Padovan 
454061386cbaSAndrei Emeltchenko 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x len %d", scid, flags,
454161386cbaSAndrei Emeltchenko 	       result, len);
45420a708f8fSGustavo F. Padovan 
4543baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, scid);
454448454079SGustavo F. Padovan 	if (!chan)
45450a708f8fSGustavo F. Padovan 		return 0;
45460a708f8fSGustavo F. Padovan 
45470a708f8fSGustavo F. Padovan 	switch (result) {
45480a708f8fSGustavo F. Padovan 	case L2CAP_CONF_SUCCESS:
454947d1ec61SGustavo F. Padovan 		l2cap_conf_rfc_get(chan, rsp->data, len);
45500e8b207eSAndrei Emeltchenko 		clear_bit(CONF_REM_CONF_PEND, &chan->conf_state);
45510a708f8fSGustavo F. Padovan 		break;
45520a708f8fSGustavo F. Padovan 
45530e8b207eSAndrei Emeltchenko 	case L2CAP_CONF_PENDING:
45540e8b207eSAndrei Emeltchenko 		set_bit(CONF_REM_CONF_PEND, &chan->conf_state);
45550e8b207eSAndrei Emeltchenko 
45560e8b207eSAndrei Emeltchenko 		if (test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
45570e8b207eSAndrei Emeltchenko 			char buf[64];
45580e8b207eSAndrei Emeltchenko 
45590e8b207eSAndrei Emeltchenko 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4560e860d2c9SBen Seri 						   buf, sizeof(buf), &result);
45610e8b207eSAndrei Emeltchenko 			if (len < 0) {
45625e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45630e8b207eSAndrei Emeltchenko 				goto done;
45640e8b207eSAndrei Emeltchenko 			}
45650e8b207eSAndrei Emeltchenko 
4566f351bc72SAndrei Emeltchenko 			if (!chan->hs_hcon) {
456779de886dSAndrei Emeltchenko 				l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
456879de886dSAndrei Emeltchenko 							0);
45695ce66b59SAndrei Emeltchenko 			} else {
45705ce66b59SAndrei Emeltchenko 				if (l2cap_check_efs(chan)) {
45715ce66b59SAndrei Emeltchenko 					amp_create_logical_link(chan);
457279de886dSAndrei Emeltchenko 					chan->ident = cmd->ident;
45730e8b207eSAndrei Emeltchenko 				}
45745ce66b59SAndrei Emeltchenko 			}
45755ce66b59SAndrei Emeltchenko 		}
45760e8b207eSAndrei Emeltchenko 		goto done;
45770e8b207eSAndrei Emeltchenko 
457898d2c3e1SBastien Nocera 	case L2CAP_CONF_UNKNOWN:
45790a708f8fSGustavo F. Padovan 	case L2CAP_CONF_UNACCEPT:
458073ffa904SGustavo F. Padovan 		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
45810a708f8fSGustavo F. Padovan 			char req[64];
45820a708f8fSGustavo F. Padovan 
45830a708f8fSGustavo F. Padovan 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
45845e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45850a708f8fSGustavo F. Padovan 				goto done;
45860a708f8fSGustavo F. Padovan 			}
45870a708f8fSGustavo F. Padovan 
45880a708f8fSGustavo F. Padovan 			/* throw out any old stored conf requests */
45890a708f8fSGustavo F. Padovan 			result = L2CAP_CONF_SUCCESS;
4590b4450035SGustavo F. Padovan 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4591e860d2c9SBen Seri 						   req, sizeof(req), &result);
45920a708f8fSGustavo F. Padovan 			if (len < 0) {
45935e4e3972SAndrei Emeltchenko 				l2cap_send_disconn_req(chan, ECONNRESET);
45940a708f8fSGustavo F. Padovan 				goto done;
45950a708f8fSGustavo F. Padovan 			}
45960a708f8fSGustavo F. Padovan 
45970a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, l2cap_get_ident(conn),
45980a708f8fSGustavo F. Padovan 				       L2CAP_CONF_REQ, len, req);
459973ffa904SGustavo F. Padovan 			chan->num_conf_req++;
46000a708f8fSGustavo F. Padovan 			if (result != L2CAP_CONF_SUCCESS)
46010a708f8fSGustavo F. Padovan 				goto done;
46020a708f8fSGustavo F. Padovan 			break;
46030a708f8fSGustavo F. Padovan 		}
460419186c7bSGustavo A. R. Silva 		fallthrough;
46050a708f8fSGustavo F. Padovan 
46060a708f8fSGustavo F. Padovan 	default:
46076be36555SAndrei Emeltchenko 		l2cap_chan_set_err(chan, ECONNRESET);
46082e0052e4SAndrei Emeltchenko 
4609ba13ccd9SMarcel Holtmann 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
46105e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
46110a708f8fSGustavo F. Padovan 		goto done;
46120a708f8fSGustavo F. Padovan 	}
46130a708f8fSGustavo F. Padovan 
461459e54bd1SAndrei Emeltchenko 	if (flags & L2CAP_CONF_FLAG_CONTINUATION)
46150a708f8fSGustavo F. Padovan 		goto done;
46160a708f8fSGustavo F. Padovan 
4617c1360a1cSGustavo F. Padovan 	set_bit(CONF_INPUT_DONE, &chan->conf_state);
46180a708f8fSGustavo F. Padovan 
4619c1360a1cSGustavo F. Padovan 	if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
462047d1ec61SGustavo F. Padovan 		set_default_fcs(chan);
46210a708f8fSGustavo F. Padovan 
4622105bdf9eSMat Martineau 		if (chan->mode == L2CAP_MODE_ERTM ||
4623105bdf9eSMat Martineau 		    chan->mode == L2CAP_MODE_STREAMING)
46243c588192SMat Martineau 			err = l2cap_ertm_init(chan);
46250a708f8fSGustavo F. Padovan 
46263c588192SMat Martineau 		if (err < 0)
46275e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
46283c588192SMat Martineau 		else
4629cf4cd009SAndrei Emeltchenko 			l2cap_chan_ready(chan);
46300a708f8fSGustavo F. Padovan 	}
46310a708f8fSGustavo F. Padovan 
46320a708f8fSGustavo F. Padovan done:
46336be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
4634d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
46353c588192SMat Martineau 	return err;
46360a708f8fSGustavo F. Padovan }
46370a708f8fSGustavo F. Padovan 
46382d792818SGustavo Padovan static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
4639cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4640cb3b3152SJohan Hedberg 				       u8 *data)
46410a708f8fSGustavo F. Padovan {
46420a708f8fSGustavo F. Padovan 	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
46430a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp rsp;
46440a708f8fSGustavo F. Padovan 	u16 dcid, scid;
464548454079SGustavo F. Padovan 	struct l2cap_chan *chan;
46460a708f8fSGustavo F. Padovan 
4647cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4648cb3b3152SJohan Hedberg 		return -EPROTO;
4649cb3b3152SJohan Hedberg 
46500a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(req->scid);
46510a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(req->dcid);
46520a708f8fSGustavo F. Padovan 
46530a708f8fSGustavo F. Padovan 	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
46540a708f8fSGustavo F. Padovan 
46553df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
46563df91ea2SAndrei Emeltchenko 
46573df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, dcid);
46583df91ea2SAndrei Emeltchenko 	if (!chan) {
46593df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
4660662d652dSJohan Hedberg 		cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
4661662d652dSJohan Hedberg 		return 0;
46623df91ea2SAndrei Emeltchenko 	}
46630a708f8fSGustavo F. Padovan 
46646c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
46656be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
46666be36555SAndrei Emeltchenko 
4667fe4128e0SGustavo F. Padovan 	rsp.dcid = cpu_to_le16(chan->scid);
4668fe4128e0SGustavo F. Padovan 	rsp.scid = cpu_to_le16(chan->dcid);
46690a708f8fSGustavo F. Padovan 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
46700a708f8fSGustavo F. Padovan 
46715ec1bbe5SGustavo Padovan 	chan->ops->set_shutdown(chan);
46720a708f8fSGustavo F. Padovan 
467348454079SGustavo F. Padovan 	l2cap_chan_del(chan, ECONNRESET);
46746be36555SAndrei Emeltchenko 
467580b98027SGustavo Padovan 	chan->ops->close(chan);
46766c08fc89SManish Mandlik 
46776c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
467861d6ef3eSMat Martineau 	l2cap_chan_put(chan);
46793df91ea2SAndrei Emeltchenko 
46803df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
46813df91ea2SAndrei Emeltchenko 
46820a708f8fSGustavo F. Padovan 	return 0;
46830a708f8fSGustavo F. Padovan }
46840a708f8fSGustavo F. Padovan 
46852d792818SGustavo Padovan static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
4686cb3b3152SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4687cb3b3152SJohan Hedberg 				       u8 *data)
46880a708f8fSGustavo F. Padovan {
46890a708f8fSGustavo F. Padovan 	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
46900a708f8fSGustavo F. Padovan 	u16 dcid, scid;
469148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
46920a708f8fSGustavo F. Padovan 
4693cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*rsp))
4694cb3b3152SJohan Hedberg 		return -EPROTO;
4695cb3b3152SJohan Hedberg 
46960a708f8fSGustavo F. Padovan 	scid = __le16_to_cpu(rsp->scid);
46970a708f8fSGustavo F. Padovan 	dcid = __le16_to_cpu(rsp->dcid);
46980a708f8fSGustavo F. Padovan 
46990a708f8fSGustavo F. Padovan 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
47000a708f8fSGustavo F. Padovan 
47013df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
47023df91ea2SAndrei Emeltchenko 
47033df91ea2SAndrei Emeltchenko 	chan = __l2cap_get_chan_by_scid(conn, scid);
47043df91ea2SAndrei Emeltchenko 	if (!chan) {
47053df91ea2SAndrei Emeltchenko 		mutex_unlock(&conn->chan_lock);
47060a708f8fSGustavo F. Padovan 		return 0;
47073df91ea2SAndrei Emeltchenko 	}
47080a708f8fSGustavo F. Padovan 
47096c08fc89SManish Mandlik 	l2cap_chan_hold(chan);
47106be36555SAndrei Emeltchenko 	l2cap_chan_lock(chan);
471148454079SGustavo F. Padovan 
471228261da8SMatias Karhumaa 	if (chan->state != BT_DISCONN) {
471328261da8SMatias Karhumaa 		l2cap_chan_unlock(chan);
47146c08fc89SManish Mandlik 		l2cap_chan_put(chan);
471528261da8SMatias Karhumaa 		mutex_unlock(&conn->chan_lock);
471628261da8SMatias Karhumaa 		return 0;
471728261da8SMatias Karhumaa 	}
471828261da8SMatias Karhumaa 
471948454079SGustavo F. Padovan 	l2cap_chan_del(chan, 0);
47206be36555SAndrei Emeltchenko 
472180b98027SGustavo Padovan 	chan->ops->close(chan);
47226c08fc89SManish Mandlik 
47236c08fc89SManish Mandlik 	l2cap_chan_unlock(chan);
472461d6ef3eSMat Martineau 	l2cap_chan_put(chan);
47253df91ea2SAndrei Emeltchenko 
47263df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
47273df91ea2SAndrei Emeltchenko 
47280a708f8fSGustavo F. Padovan 	return 0;
47290a708f8fSGustavo F. Padovan }
47300a708f8fSGustavo F. Padovan 
47312d792818SGustavo Padovan static inline int l2cap_information_req(struct l2cap_conn *conn,
4732cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4733cb3b3152SJohan Hedberg 					u8 *data)
47340a708f8fSGustavo F. Padovan {
47350a708f8fSGustavo F. Padovan 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
47360a708f8fSGustavo F. Padovan 	u16 type;
47370a708f8fSGustavo F. Padovan 
4738cb3b3152SJohan Hedberg 	if (cmd_len != sizeof(*req))
4739cb3b3152SJohan Hedberg 		return -EPROTO;
4740cb3b3152SJohan Hedberg 
47410a708f8fSGustavo F. Padovan 	type = __le16_to_cpu(req->type);
47420a708f8fSGustavo F. Padovan 
47430a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x", type);
47440a708f8fSGustavo F. Padovan 
47450a708f8fSGustavo F. Padovan 	if (type == L2CAP_IT_FEAT_MASK) {
47460a708f8fSGustavo F. Padovan 		u8 buf[8];
47470a708f8fSGustavo F. Padovan 		u32 feat_mask = l2cap_feat_mask;
47480a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
4749dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
4750dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
47510a708f8fSGustavo F. Padovan 		if (!disable_ertm)
47520a708f8fSGustavo F. Padovan 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
47530a708f8fSGustavo F. Padovan 				| L2CAP_FEAT_FCS;
47540bd49fc7SJohan Hedberg 		if (conn->local_fixed_chan & L2CAP_FC_A2MP)
47556327eb98SAndrei Emeltchenko 			feat_mask |= L2CAP_FEAT_EXT_FLOW
47566327eb98SAndrei Emeltchenko 				| L2CAP_FEAT_EXT_WINDOW;
4757a5fd6f30SAndrei Emeltchenko 
47580a708f8fSGustavo F. Padovan 		put_unaligned_le32(feat_mask, rsp->data);
47592d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47602d792818SGustavo Padovan 			       buf);
47610a708f8fSGustavo F. Padovan 	} else if (type == L2CAP_IT_FIXED_CHAN) {
47620a708f8fSGustavo F. Padovan 		u8 buf[12];
47630a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
476450a147cdSMat Martineau 
4765dcf4adbfSJoe Perches 		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
4766dcf4adbfSJoe Perches 		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
47670bd49fc7SJohan Hedberg 		rsp->data[0] = conn->local_fixed_chan;
47680bd49fc7SJohan Hedberg 		memset(rsp->data + 1, 0, 7);
47692d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
47702d792818SGustavo Padovan 			       buf);
47710a708f8fSGustavo F. Padovan 	} else {
47720a708f8fSGustavo F. Padovan 		struct l2cap_info_rsp rsp;
47730a708f8fSGustavo F. Padovan 		rsp.type   = cpu_to_le16(type);
4774dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
47752d792818SGustavo Padovan 		l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp),
47762d792818SGustavo Padovan 			       &rsp);
47770a708f8fSGustavo F. Padovan 	}
47780a708f8fSGustavo F. Padovan 
47790a708f8fSGustavo F. Padovan 	return 0;
47800a708f8fSGustavo F. Padovan }
47810a708f8fSGustavo F. Padovan 
47822d792818SGustavo Padovan static inline int l2cap_information_rsp(struct l2cap_conn *conn,
4783cb3b3152SJohan Hedberg 					struct l2cap_cmd_hdr *cmd, u16 cmd_len,
4784cb3b3152SJohan Hedberg 					u8 *data)
47850a708f8fSGustavo F. Padovan {
47860a708f8fSGustavo F. Padovan 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
47870a708f8fSGustavo F. Padovan 	u16 type, result;
47880a708f8fSGustavo F. Padovan 
47893f6fa3d4SJaganath Kanakkassery 	if (cmd_len < sizeof(*rsp))
4790cb3b3152SJohan Hedberg 		return -EPROTO;
4791cb3b3152SJohan Hedberg 
47920a708f8fSGustavo F. Padovan 	type   = __le16_to_cpu(rsp->type);
47930a708f8fSGustavo F. Padovan 	result = __le16_to_cpu(rsp->result);
47940a708f8fSGustavo F. Padovan 
47950a708f8fSGustavo F. Padovan 	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
47960a708f8fSGustavo F. Padovan 
4797e90165beSAndrei Emeltchenko 	/* L2CAP Info req/rsp are unbound to channels, add extra checks */
4798e90165beSAndrei Emeltchenko 	if (cmd->ident != conn->info_ident ||
4799e90165beSAndrei Emeltchenko 	    conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
4800e90165beSAndrei Emeltchenko 		return 0;
4801e90165beSAndrei Emeltchenko 
480217cd3f37SUlisses Furquim 	cancel_delayed_work(&conn->info_timer);
48030a708f8fSGustavo F. Padovan 
48040a708f8fSGustavo F. Padovan 	if (result != L2CAP_IR_SUCCESS) {
48050a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
48060a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
48070a708f8fSGustavo F. Padovan 
48080a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
48090a708f8fSGustavo F. Padovan 
48100a708f8fSGustavo F. Padovan 		return 0;
48110a708f8fSGustavo F. Padovan 	}
48120a708f8fSGustavo F. Padovan 
4813978c93b9SAndrei Emeltchenko 	switch (type) {
4814978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FEAT_MASK:
48150a708f8fSGustavo F. Padovan 		conn->feat_mask = get_unaligned_le32(rsp->data);
48160a708f8fSGustavo F. Padovan 
48170a708f8fSGustavo F. Padovan 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
48180a708f8fSGustavo F. Padovan 			struct l2cap_info_req req;
4819dcf4adbfSJoe Perches 			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
48200a708f8fSGustavo F. Padovan 
48210a708f8fSGustavo F. Padovan 			conn->info_ident = l2cap_get_ident(conn);
48220a708f8fSGustavo F. Padovan 
48230a708f8fSGustavo F. Padovan 			l2cap_send_cmd(conn, conn->info_ident,
48240a708f8fSGustavo F. Padovan 				       L2CAP_INFO_REQ, sizeof(req), &req);
48250a708f8fSGustavo F. Padovan 		} else {
48260a708f8fSGustavo F. Padovan 			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
48270a708f8fSGustavo F. Padovan 			conn->info_ident = 0;
48280a708f8fSGustavo F. Padovan 
48290a708f8fSGustavo F. Padovan 			l2cap_conn_start(conn);
48300a708f8fSGustavo F. Padovan 		}
4831978c93b9SAndrei Emeltchenko 		break;
4832978c93b9SAndrei Emeltchenko 
4833978c93b9SAndrei Emeltchenko 	case L2CAP_IT_FIXED_CHAN:
48340bd49fc7SJohan Hedberg 		conn->remote_fixed_chan = rsp->data[0];
48350a708f8fSGustavo F. Padovan 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
48360a708f8fSGustavo F. Padovan 		conn->info_ident = 0;
48370a708f8fSGustavo F. Padovan 
48380a708f8fSGustavo F. Padovan 		l2cap_conn_start(conn);
4839978c93b9SAndrei Emeltchenko 		break;
48400a708f8fSGustavo F. Padovan 	}
48410a708f8fSGustavo F. Padovan 
48420a708f8fSGustavo F. Padovan 	return 0;
48430a708f8fSGustavo F. Padovan }
48440a708f8fSGustavo F. Padovan 
48451700915fSMat Martineau static int l2cap_create_channel_req(struct l2cap_conn *conn,
48462d792818SGustavo Padovan 				    struct l2cap_cmd_hdr *cmd,
48472d792818SGustavo Padovan 				    u16 cmd_len, void *data)
4848f94ff6ffSMat Martineau {
4849f94ff6ffSMat Martineau 	struct l2cap_create_chan_req *req = data;
48506e1df6a6SAndrei Emeltchenko 	struct l2cap_create_chan_rsp rsp;
48511700915fSMat Martineau 	struct l2cap_chan *chan;
48526e1df6a6SAndrei Emeltchenko 	struct hci_dev *hdev;
4853f94ff6ffSMat Martineau 	u16 psm, scid;
4854f94ff6ffSMat Martineau 
4855f94ff6ffSMat Martineau 	if (cmd_len != sizeof(*req))
4856f94ff6ffSMat Martineau 		return -EPROTO;
4857f94ff6ffSMat Martineau 
48580bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
4859f94ff6ffSMat Martineau 		return -EINVAL;
4860f94ff6ffSMat Martineau 
4861f94ff6ffSMat Martineau 	psm = le16_to_cpu(req->psm);
4862f94ff6ffSMat Martineau 	scid = le16_to_cpu(req->scid);
4863f94ff6ffSMat Martineau 
4864ad0ac6caSAndrei Emeltchenko 	BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
4865f94ff6ffSMat Martineau 
48666e1df6a6SAndrei Emeltchenko 	/* For controller id 0 make BR/EDR connection */
48676ed971caSMarcel Holtmann 	if (req->amp_id == AMP_ID_BREDR) {
48686e1df6a6SAndrei Emeltchenko 		l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48696e1df6a6SAndrei Emeltchenko 			      req->amp_id);
48706e1df6a6SAndrei Emeltchenko 		return 0;
48716e1df6a6SAndrei Emeltchenko 	}
48721700915fSMat Martineau 
48731700915fSMat Martineau 	/* Validate AMP controller id */
48741700915fSMat Martineau 	hdev = hci_dev_get(req->amp_id);
48756e1df6a6SAndrei Emeltchenko 	if (!hdev)
48766e1df6a6SAndrei Emeltchenko 		goto error;
48771700915fSMat Martineau 
48786e1df6a6SAndrei Emeltchenko 	if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
48796e1df6a6SAndrei Emeltchenko 		hci_dev_put(hdev);
48806e1df6a6SAndrei Emeltchenko 		goto error;
48816e1df6a6SAndrei Emeltchenko 	}
48826e1df6a6SAndrei Emeltchenko 
48836e1df6a6SAndrei Emeltchenko 	chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
48846e1df6a6SAndrei Emeltchenko 			     req->amp_id);
48856e1df6a6SAndrei Emeltchenko 	if (chan) {
48866e1df6a6SAndrei Emeltchenko 		struct amp_mgr *mgr = conn->hcon->amp_mgr;
48876e1df6a6SAndrei Emeltchenko 		struct hci_conn *hs_hcon;
48886e1df6a6SAndrei Emeltchenko 
488998e0f7eaSMarcel Holtmann 		hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
489098e0f7eaSMarcel Holtmann 						  &conn->hcon->dst);
48916e1df6a6SAndrei Emeltchenko 		if (!hs_hcon) {
48926e1df6a6SAndrei Emeltchenko 			hci_dev_put(hdev);
4893662d652dSJohan Hedberg 			cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
4894662d652dSJohan Hedberg 					       chan->dcid);
4895662d652dSJohan Hedberg 			return 0;
48966e1df6a6SAndrei Emeltchenko 		}
48976e1df6a6SAndrei Emeltchenko 
48986e1df6a6SAndrei Emeltchenko 		BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
48996e1df6a6SAndrei Emeltchenko 
49006e1df6a6SAndrei Emeltchenko 		mgr->bredr_chan = chan;
49016e1df6a6SAndrei Emeltchenko 		chan->hs_hcon = hs_hcon;
4902fd45bf4cSAndrei Emeltchenko 		chan->fcs = L2CAP_FCS_NONE;
49036e1df6a6SAndrei Emeltchenko 		conn->mtu = hdev->block_mtu;
49046e1df6a6SAndrei Emeltchenko 	}
49056e1df6a6SAndrei Emeltchenko 
49066e1df6a6SAndrei Emeltchenko 	hci_dev_put(hdev);
49076e1df6a6SAndrei Emeltchenko 
49086e1df6a6SAndrei Emeltchenko 	return 0;
49096e1df6a6SAndrei Emeltchenko 
49106e1df6a6SAndrei Emeltchenko error:
4911f94ff6ffSMat Martineau 	rsp.dcid = 0;
4912f94ff6ffSMat Martineau 	rsp.scid = cpu_to_le16(scid);
4913dcf4adbfSJoe Perches 	rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
4914dcf4adbfSJoe Perches 	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
4915f94ff6ffSMat Martineau 
4916f94ff6ffSMat Martineau 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
4917f94ff6ffSMat Martineau 		       sizeof(rsp), &rsp);
4918f94ff6ffSMat Martineau 
4919dc280801SJohan Hedberg 	return 0;
4920f94ff6ffSMat Martineau }
4921f94ff6ffSMat Martineau 
49228eb200bdSMat Martineau static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
49238eb200bdSMat Martineau {
49248eb200bdSMat Martineau 	struct l2cap_move_chan_req req;
49258eb200bdSMat Martineau 	u8 ident;
49268eb200bdSMat Martineau 
49278eb200bdSMat Martineau 	BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
49288eb200bdSMat Martineau 
49298eb200bdSMat Martineau 	ident = l2cap_get_ident(chan->conn);
49308eb200bdSMat Martineau 	chan->ident = ident;
49318eb200bdSMat Martineau 
49328eb200bdSMat Martineau 	req.icid = cpu_to_le16(chan->scid);
49338eb200bdSMat Martineau 	req.dest_amp_id = dest_amp_id;
49348eb200bdSMat Martineau 
49358eb200bdSMat Martineau 	l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
49368eb200bdSMat Martineau 		       &req);
49378eb200bdSMat Martineau 
49388eb200bdSMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
49398eb200bdSMat Martineau }
49408eb200bdSMat Martineau 
49411500109bSMat Martineau static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
49428d5a04a1SMat Martineau {
49438d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp rsp;
49448d5a04a1SMat Martineau 
49451500109bSMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
49468d5a04a1SMat Martineau 
49471500109bSMat Martineau 	rsp.icid = cpu_to_le16(chan->dcid);
49488d5a04a1SMat Martineau 	rsp.result = cpu_to_le16(result);
49498d5a04a1SMat Martineau 
49501500109bSMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
49511500109bSMat Martineau 		       sizeof(rsp), &rsp);
49528d5a04a1SMat Martineau }
49538d5a04a1SMat Martineau 
49545b155ef9SMat Martineau static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
49558d5a04a1SMat Martineau {
49568d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49578d5a04a1SMat Martineau 
49585b155ef9SMat Martineau 	BT_DBG("chan %p, result 0x%4.4x", chan, result);
49598d5a04a1SMat Martineau 
49605b155ef9SMat Martineau 	chan->ident = l2cap_get_ident(chan->conn);
49618d5a04a1SMat Martineau 
49625b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(chan->scid);
49638d5a04a1SMat Martineau 	cfm.result = cpu_to_le16(result);
49648d5a04a1SMat Martineau 
49655b155ef9SMat Martineau 	l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
49665b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49675b155ef9SMat Martineau 
49685b155ef9SMat Martineau 	__set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
49695b155ef9SMat Martineau }
49705b155ef9SMat Martineau 
49715b155ef9SMat Martineau static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
49725b155ef9SMat Martineau {
49735b155ef9SMat Martineau 	struct l2cap_move_chan_cfm cfm;
49745b155ef9SMat Martineau 
49755b155ef9SMat Martineau 	BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
49765b155ef9SMat Martineau 
49775b155ef9SMat Martineau 	cfm.icid = cpu_to_le16(icid);
4978dcf4adbfSJoe Perches 	cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
49795b155ef9SMat Martineau 
49805b155ef9SMat Martineau 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
49815b155ef9SMat Martineau 		       sizeof(cfm), &cfm);
49828d5a04a1SMat Martineau }
49838d5a04a1SMat Martineau 
49848d5a04a1SMat Martineau static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
49858d5a04a1SMat Martineau 					 u16 icid)
49868d5a04a1SMat Martineau {
49878d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp rsp;
49888d5a04a1SMat Martineau 
4989ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
49908d5a04a1SMat Martineau 
49918d5a04a1SMat Martineau 	rsp.icid = cpu_to_le16(icid);
49928d5a04a1SMat Martineau 	l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
49938d5a04a1SMat Martineau }
49948d5a04a1SMat Martineau 
49955f3847a4SMat Martineau static void __release_logical_link(struct l2cap_chan *chan)
49965f3847a4SMat Martineau {
49975f3847a4SMat Martineau 	chan->hs_hchan = NULL;
49985f3847a4SMat Martineau 	chan->hs_hcon = NULL;
49995f3847a4SMat Martineau 
50005f3847a4SMat Martineau 	/* Placeholder - release the logical link */
50015f3847a4SMat Martineau }
50025f3847a4SMat Martineau 
50031500109bSMat Martineau static void l2cap_logical_fail(struct l2cap_chan *chan)
50041500109bSMat Martineau {
50051500109bSMat Martineau 	/* Logical link setup failed */
50061500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
50071500109bSMat Martineau 		/* Create channel failure, disconnect */
50085e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
50091500109bSMat Martineau 		return;
50101500109bSMat Martineau 	}
50111500109bSMat Martineau 
50121500109bSMat Martineau 	switch (chan->move_role) {
50131500109bSMat Martineau 	case L2CAP_MOVE_ROLE_RESPONDER:
50141500109bSMat Martineau 		l2cap_move_done(chan);
50151500109bSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
50161500109bSMat Martineau 		break;
50171500109bSMat Martineau 	case L2CAP_MOVE_ROLE_INITIATOR:
50181500109bSMat Martineau 		if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
50191500109bSMat Martineau 		    chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
50201500109bSMat Martineau 			/* Remote has only sent pending or
50211500109bSMat Martineau 			 * success responses, clean up
50221500109bSMat Martineau 			 */
50231500109bSMat Martineau 			l2cap_move_done(chan);
50241500109bSMat Martineau 		}
50251500109bSMat Martineau 
50261500109bSMat Martineau 		/* Other amp move states imply that the move
50271500109bSMat Martineau 		 * has already aborted
50281500109bSMat Martineau 		 */
50291500109bSMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
50301500109bSMat Martineau 		break;
50311500109bSMat Martineau 	}
50321500109bSMat Martineau }
50331500109bSMat Martineau 
50341500109bSMat Martineau static void l2cap_logical_finish_create(struct l2cap_chan *chan,
50351500109bSMat Martineau 					struct hci_chan *hchan)
50361500109bSMat Martineau {
50371500109bSMat Martineau 	struct l2cap_conf_rsp rsp;
50381500109bSMat Martineau 
5039336178a3SAndrei Emeltchenko 	chan->hs_hchan = hchan;
50401500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
50411500109bSMat Martineau 
504235ba9561SAndrei Emeltchenko 	l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
50431500109bSMat Martineau 
50441500109bSMat Martineau 	if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
5045fe79c6feSAndrei Emeltchenko 		int err;
50461500109bSMat Martineau 
50471500109bSMat Martineau 		set_default_fcs(chan);
50481500109bSMat Martineau 
50491500109bSMat Martineau 		err = l2cap_ertm_init(chan);
50501500109bSMat Martineau 		if (err < 0)
50515e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, -err);
50521500109bSMat Martineau 		else
50531500109bSMat Martineau 			l2cap_chan_ready(chan);
50541500109bSMat Martineau 	}
50551500109bSMat Martineau }
50561500109bSMat Martineau 
50571500109bSMat Martineau static void l2cap_logical_finish_move(struct l2cap_chan *chan,
50581500109bSMat Martineau 				      struct hci_chan *hchan)
50591500109bSMat Martineau {
50601500109bSMat Martineau 	chan->hs_hcon = hchan->conn;
50611500109bSMat Martineau 	chan->hs_hcon->l2cap_data = chan->conn;
50621500109bSMat Martineau 
50631500109bSMat Martineau 	BT_DBG("move_state %d", chan->move_state);
50641500109bSMat Martineau 
50651500109bSMat Martineau 	switch (chan->move_state) {
50661500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
50671500109bSMat Martineau 		/* Move confirm will be sent after a success
50681500109bSMat Martineau 		 * response is received
50691500109bSMat Martineau 		 */
50701500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
50711500109bSMat Martineau 		break;
50721500109bSMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_CFM:
50731500109bSMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
50741500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
50751500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
50761500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
50771500109bSMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
50781500109bSMat Martineau 		} else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
50791500109bSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
50801500109bSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
50811500109bSMat Martineau 		}
50821500109bSMat Martineau 		break;
50831500109bSMat Martineau 	default:
50841500109bSMat Martineau 		/* Move was not in expected state, free the channel */
50851500109bSMat Martineau 		__release_logical_link(chan);
50861500109bSMat Martineau 
50871500109bSMat Martineau 		chan->move_state = L2CAP_MOVE_STABLE;
50881500109bSMat Martineau 	}
50891500109bSMat Martineau }
50901500109bSMat Martineau 
50911500109bSMat Martineau /* Call with chan locked */
509227695fb4SAndrei Emeltchenko void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
50935b155ef9SMat Martineau 		       u8 status)
50945b155ef9SMat Martineau {
50951500109bSMat Martineau 	BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
50961500109bSMat Martineau 
50971500109bSMat Martineau 	if (status) {
50981500109bSMat Martineau 		l2cap_logical_fail(chan);
50991500109bSMat Martineau 		__release_logical_link(chan);
51005b155ef9SMat Martineau 		return;
51015b155ef9SMat Martineau 	}
51025b155ef9SMat Martineau 
51031500109bSMat Martineau 	if (chan->state != BT_CONNECTED) {
51041500109bSMat Martineau 		/* Ignore logical link if channel is on BR/EDR */
51056ed971caSMarcel Holtmann 		if (chan->local_amp_id != AMP_ID_BREDR)
51061500109bSMat Martineau 			l2cap_logical_finish_create(chan, hchan);
51071500109bSMat Martineau 	} else {
51081500109bSMat Martineau 		l2cap_logical_finish_move(chan, hchan);
51091500109bSMat Martineau 	}
51101500109bSMat Martineau }
51111500109bSMat Martineau 
51123f7a56c4SMat Martineau void l2cap_move_start(struct l2cap_chan *chan)
51133f7a56c4SMat Martineau {
51143f7a56c4SMat Martineau 	BT_DBG("chan %p", chan);
51153f7a56c4SMat Martineau 
51166ed971caSMarcel Holtmann 	if (chan->local_amp_id == AMP_ID_BREDR) {
51173f7a56c4SMat Martineau 		if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
51183f7a56c4SMat Martineau 			return;
51193f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
51203f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
51213f7a56c4SMat Martineau 		/* Placeholder - start physical link setup */
51223f7a56c4SMat Martineau 	} else {
51233f7a56c4SMat Martineau 		chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
51243f7a56c4SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
51253f7a56c4SMat Martineau 		chan->move_id = 0;
51263f7a56c4SMat Martineau 		l2cap_move_setup(chan);
51273f7a56c4SMat Martineau 		l2cap_send_move_chan_req(chan, 0);
51283f7a56c4SMat Martineau 	}
51293f7a56c4SMat Martineau }
51303f7a56c4SMat Martineau 
51318eb200bdSMat Martineau static void l2cap_do_create(struct l2cap_chan *chan, int result,
51328eb200bdSMat Martineau 			    u8 local_amp_id, u8 remote_amp_id)
51338eb200bdSMat Martineau {
513462748ca1SAndrei Emeltchenko 	BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
513562748ca1SAndrei Emeltchenko 	       local_amp_id, remote_amp_id);
513662748ca1SAndrei Emeltchenko 
513712d6cc60SAndrei Emeltchenko 	chan->fcs = L2CAP_FCS_NONE;
513812d6cc60SAndrei Emeltchenko 
513962748ca1SAndrei Emeltchenko 	/* Outgoing channel on AMP */
514062748ca1SAndrei Emeltchenko 	if (chan->state == BT_CONNECT) {
514162748ca1SAndrei Emeltchenko 		if (result == L2CAP_CR_SUCCESS) {
514262748ca1SAndrei Emeltchenko 			chan->local_amp_id = local_amp_id;
514362748ca1SAndrei Emeltchenko 			l2cap_send_create_chan_req(chan, remote_amp_id);
514462748ca1SAndrei Emeltchenko 		} else {
514562748ca1SAndrei Emeltchenko 			/* Revert to BR/EDR connect */
514662748ca1SAndrei Emeltchenko 			l2cap_send_conn_req(chan);
514762748ca1SAndrei Emeltchenko 		}
514862748ca1SAndrei Emeltchenko 
514962748ca1SAndrei Emeltchenko 		return;
515062748ca1SAndrei Emeltchenko 	}
515162748ca1SAndrei Emeltchenko 
515262748ca1SAndrei Emeltchenko 	/* Incoming channel on AMP */
515362748ca1SAndrei Emeltchenko 	if (__l2cap_no_conn_pending(chan)) {
51548eb200bdSMat Martineau 		struct l2cap_conn_rsp rsp;
51558eb200bdSMat Martineau 		char buf[128];
51568eb200bdSMat Martineau 		rsp.scid = cpu_to_le16(chan->dcid);
51578eb200bdSMat Martineau 		rsp.dcid = cpu_to_le16(chan->scid);
51588eb200bdSMat Martineau 
51598eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
51608eb200bdSMat Martineau 			/* Send successful response */
5161dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
5162dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51638eb200bdSMat Martineau 		} else {
51648eb200bdSMat Martineau 			/* Send negative response */
5165dcf4adbfSJoe Perches 			rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
5166dcf4adbfSJoe Perches 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
51678eb200bdSMat Martineau 		}
51688eb200bdSMat Martineau 
51698eb200bdSMat Martineau 		l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
51708eb200bdSMat Martineau 			       sizeof(rsp), &rsp);
51718eb200bdSMat Martineau 
51728eb200bdSMat Martineau 		if (result == L2CAP_CR_SUCCESS) {
5173f93fa273SGustavo Padovan 			l2cap_state_change(chan, BT_CONFIG);
51748eb200bdSMat Martineau 			set_bit(CONF_REQ_SENT, &chan->conf_state);
51758eb200bdSMat Martineau 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
51768eb200bdSMat Martineau 				       L2CAP_CONF_REQ,
5177e860d2c9SBen Seri 				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
51788eb200bdSMat Martineau 			chan->num_conf_req++;
51798eb200bdSMat Martineau 		}
51808eb200bdSMat Martineau 	}
51818eb200bdSMat Martineau }
51828eb200bdSMat Martineau 
51838eb200bdSMat Martineau static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
51848eb200bdSMat Martineau 				   u8 remote_amp_id)
51858eb200bdSMat Martineau {
51868eb200bdSMat Martineau 	l2cap_move_setup(chan);
51878eb200bdSMat Martineau 	chan->move_id = local_amp_id;
51888eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_WAIT_RSP;
51898eb200bdSMat Martineau 
51908eb200bdSMat Martineau 	l2cap_send_move_chan_req(chan, remote_amp_id);
51918eb200bdSMat Martineau }
51928eb200bdSMat Martineau 
51938eb200bdSMat Martineau static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
51948eb200bdSMat Martineau {
51958eb200bdSMat Martineau 	struct hci_chan *hchan = NULL;
51968eb200bdSMat Martineau 
51978eb200bdSMat Martineau 	/* Placeholder - get hci_chan for logical link */
51988eb200bdSMat Martineau 
51998eb200bdSMat Martineau 	if (hchan) {
52008eb200bdSMat Martineau 		if (hchan->state == BT_CONNECTED) {
52018eb200bdSMat Martineau 			/* Logical link is ready to go */
52028eb200bdSMat Martineau 			chan->hs_hcon = hchan->conn;
52038eb200bdSMat Martineau 			chan->hs_hcon->l2cap_data = chan->conn;
52048eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
52058eb200bdSMat Martineau 			l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
52068eb200bdSMat Martineau 
52078eb200bdSMat Martineau 			l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
52088eb200bdSMat Martineau 		} else {
52098eb200bdSMat Martineau 			/* Wait for logical link to be ready */
52108eb200bdSMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
52118eb200bdSMat Martineau 		}
52128eb200bdSMat Martineau 	} else {
52138eb200bdSMat Martineau 		/* Logical link not available */
52148eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
52158eb200bdSMat Martineau 	}
52168eb200bdSMat Martineau }
52178eb200bdSMat Martineau 
52188eb200bdSMat Martineau static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
52198eb200bdSMat Martineau {
52208eb200bdSMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
52218eb200bdSMat Martineau 		u8 rsp_result;
52228eb200bdSMat Martineau 		if (result == -EINVAL)
52238eb200bdSMat Martineau 			rsp_result = L2CAP_MR_BAD_ID;
52248eb200bdSMat Martineau 		else
52258eb200bdSMat Martineau 			rsp_result = L2CAP_MR_NOT_ALLOWED;
52268eb200bdSMat Martineau 
52278eb200bdSMat Martineau 		l2cap_send_move_chan_rsp(chan, rsp_result);
52288eb200bdSMat Martineau 	}
52298eb200bdSMat Martineau 
52308eb200bdSMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_NONE;
52318eb200bdSMat Martineau 	chan->move_state = L2CAP_MOVE_STABLE;
52328eb200bdSMat Martineau 
52338eb200bdSMat Martineau 	/* Restart data transmission */
52348eb200bdSMat Martineau 	l2cap_ertm_send(chan);
52358eb200bdSMat Martineau }
52368eb200bdSMat Martineau 
5237a514b17fSAndrei Emeltchenko /* Invoke with locked chan */
5238a514b17fSAndrei Emeltchenko void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
52398eb200bdSMat Martineau {
5240770bfefaSAndrei Emeltchenko 	u8 local_amp_id = chan->local_amp_id;
5241fffadc08SAndrei Emeltchenko 	u8 remote_amp_id = chan->remote_amp_id;
5242770bfefaSAndrei Emeltchenko 
52438eb200bdSMat Martineau 	BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
52448eb200bdSMat Martineau 	       chan, result, local_amp_id, remote_amp_id);
52458eb200bdSMat Martineau 
5246df66499aSDan Carpenter 	if (chan->state == BT_DISCONN || chan->state == BT_CLOSED)
52478eb200bdSMat Martineau 		return;
52488eb200bdSMat Martineau 
52498eb200bdSMat Martineau 	if (chan->state != BT_CONNECTED) {
52508eb200bdSMat Martineau 		l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
52518eb200bdSMat Martineau 	} else if (result != L2CAP_MR_SUCCESS) {
52528eb200bdSMat Martineau 		l2cap_do_move_cancel(chan, result);
52538eb200bdSMat Martineau 	} else {
52548eb200bdSMat Martineau 		switch (chan->move_role) {
52558eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_INITIATOR:
52568eb200bdSMat Martineau 			l2cap_do_move_initiate(chan, local_amp_id,
52578eb200bdSMat Martineau 					       remote_amp_id);
52588eb200bdSMat Martineau 			break;
52598eb200bdSMat Martineau 		case L2CAP_MOVE_ROLE_RESPONDER:
52608eb200bdSMat Martineau 			l2cap_do_move_respond(chan, result);
52618eb200bdSMat Martineau 			break;
52628eb200bdSMat Martineau 		default:
52638eb200bdSMat Martineau 			l2cap_do_move_cancel(chan, result);
52648eb200bdSMat Martineau 			break;
52658eb200bdSMat Martineau 		}
52668eb200bdSMat Martineau 	}
52678eb200bdSMat Martineau }
52688eb200bdSMat Martineau 
52698d5a04a1SMat Martineau static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
5270ad0ac6caSAndrei Emeltchenko 					 struct l2cap_cmd_hdr *cmd,
5271ad0ac6caSAndrei Emeltchenko 					 u16 cmd_len, void *data)
52728d5a04a1SMat Martineau {
52738d5a04a1SMat Martineau 	struct l2cap_move_chan_req *req = data;
52741500109bSMat Martineau 	struct l2cap_move_chan_rsp rsp;
527502b0fbb9SMat Martineau 	struct l2cap_chan *chan;
52768d5a04a1SMat Martineau 	u16 icid = 0;
52778d5a04a1SMat Martineau 	u16 result = L2CAP_MR_NOT_ALLOWED;
52788d5a04a1SMat Martineau 
52798d5a04a1SMat Martineau 	if (cmd_len != sizeof(*req))
52808d5a04a1SMat Martineau 		return -EPROTO;
52818d5a04a1SMat Martineau 
52828d5a04a1SMat Martineau 	icid = le16_to_cpu(req->icid);
52838d5a04a1SMat Martineau 
5284ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
52858d5a04a1SMat Martineau 
52860bd49fc7SJohan Hedberg 	if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
52878d5a04a1SMat Martineau 		return -EINVAL;
52888d5a04a1SMat Martineau 
528902b0fbb9SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
529002b0fbb9SMat Martineau 	if (!chan) {
52911500109bSMat Martineau 		rsp.icid = cpu_to_le16(icid);
5292dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
52931500109bSMat Martineau 		l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
52941500109bSMat Martineau 			       sizeof(rsp), &rsp);
529502b0fbb9SMat Martineau 		return 0;
529602b0fbb9SMat Martineau 	}
529702b0fbb9SMat Martineau 
52981500109bSMat Martineau 	chan->ident = cmd->ident;
52991500109bSMat Martineau 
530002b0fbb9SMat Martineau 	if (chan->scid < L2CAP_CID_DYN_START ||
530102b0fbb9SMat Martineau 	    chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
530202b0fbb9SMat Martineau 	    (chan->mode != L2CAP_MODE_ERTM &&
530302b0fbb9SMat Martineau 	     chan->mode != L2CAP_MODE_STREAMING)) {
530402b0fbb9SMat Martineau 		result = L2CAP_MR_NOT_ALLOWED;
530502b0fbb9SMat Martineau 		goto send_move_response;
530602b0fbb9SMat Martineau 	}
530702b0fbb9SMat Martineau 
530802b0fbb9SMat Martineau 	if (chan->local_amp_id == req->dest_amp_id) {
530902b0fbb9SMat Martineau 		result = L2CAP_MR_SAME_ID;
531002b0fbb9SMat Martineau 		goto send_move_response;
531102b0fbb9SMat Martineau 	}
531202b0fbb9SMat Martineau 
53136ed971caSMarcel Holtmann 	if (req->dest_amp_id != AMP_ID_BREDR) {
531402b0fbb9SMat Martineau 		struct hci_dev *hdev;
531502b0fbb9SMat Martineau 		hdev = hci_dev_get(req->dest_amp_id);
531602b0fbb9SMat Martineau 		if (!hdev || hdev->dev_type != HCI_AMP ||
531702b0fbb9SMat Martineau 		    !test_bit(HCI_UP, &hdev->flags)) {
531802b0fbb9SMat Martineau 			if (hdev)
531902b0fbb9SMat Martineau 				hci_dev_put(hdev);
532002b0fbb9SMat Martineau 
532102b0fbb9SMat Martineau 			result = L2CAP_MR_BAD_ID;
532202b0fbb9SMat Martineau 			goto send_move_response;
532302b0fbb9SMat Martineau 		}
532402b0fbb9SMat Martineau 		hci_dev_put(hdev);
532502b0fbb9SMat Martineau 	}
532602b0fbb9SMat Martineau 
532702b0fbb9SMat Martineau 	/* Detect a move collision.  Only send a collision response
532802b0fbb9SMat Martineau 	 * if this side has "lost", otherwise proceed with the move.
532902b0fbb9SMat Martineau 	 * The winner has the larger bd_addr.
533002b0fbb9SMat Martineau 	 */
533102b0fbb9SMat Martineau 	if ((__chan_is_moving(chan) ||
533202b0fbb9SMat Martineau 	     chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
53336f59b904SMarcel Holtmann 	    bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
533402b0fbb9SMat Martineau 		result = L2CAP_MR_COLLISION;
533502b0fbb9SMat Martineau 		goto send_move_response;
533602b0fbb9SMat Martineau 	}
533702b0fbb9SMat Martineau 
533802b0fbb9SMat Martineau 	chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
533902b0fbb9SMat Martineau 	l2cap_move_setup(chan);
534002b0fbb9SMat Martineau 	chan->move_id = req->dest_amp_id;
534102b0fbb9SMat Martineau 
53426ed971caSMarcel Holtmann 	if (req->dest_amp_id == AMP_ID_BREDR) {
534302b0fbb9SMat Martineau 		/* Moving to BR/EDR */
534402b0fbb9SMat Martineau 		if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
534502b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
534602b0fbb9SMat Martineau 			result = L2CAP_MR_PEND;
534702b0fbb9SMat Martineau 		} else {
534802b0fbb9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
534902b0fbb9SMat Martineau 			result = L2CAP_MR_SUCCESS;
535002b0fbb9SMat Martineau 		}
535102b0fbb9SMat Martineau 	} else {
535202b0fbb9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
535302b0fbb9SMat Martineau 		/* Placeholder - uncomment when amp functions are available */
535402b0fbb9SMat Martineau 		/*amp_accept_physical(chan, req->dest_amp_id);*/
535502b0fbb9SMat Martineau 		result = L2CAP_MR_PEND;
535602b0fbb9SMat Martineau 	}
535702b0fbb9SMat Martineau 
535802b0fbb9SMat Martineau send_move_response:
53591500109bSMat Martineau 	l2cap_send_move_chan_rsp(chan, result);
53608d5a04a1SMat Martineau 
536102b0fbb9SMat Martineau 	l2cap_chan_unlock(chan);
5362d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
536302b0fbb9SMat Martineau 
53648d5a04a1SMat Martineau 	return 0;
53658d5a04a1SMat Martineau }
53668d5a04a1SMat Martineau 
53675b155ef9SMat Martineau static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
53685b155ef9SMat Martineau {
53695b155ef9SMat Martineau 	struct l2cap_chan *chan;
53705b155ef9SMat Martineau 	struct hci_chan *hchan = NULL;
53715b155ef9SMat Martineau 
53725b155ef9SMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
53735b155ef9SMat Martineau 	if (!chan) {
53745b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
53755b155ef9SMat Martineau 		return;
53765b155ef9SMat Martineau 	}
53775b155ef9SMat Martineau 
53785b155ef9SMat Martineau 	__clear_chan_timer(chan);
53795b155ef9SMat Martineau 	if (result == L2CAP_MR_PEND)
53805b155ef9SMat Martineau 		__set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
53815b155ef9SMat Martineau 
53825b155ef9SMat Martineau 	switch (chan->move_state) {
53835b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_LOGICAL_COMP:
53845b155ef9SMat Martineau 		/* Move confirm will be sent when logical link
53855b155ef9SMat Martineau 		 * is complete.
53865b155ef9SMat Martineau 		 */
53875b155ef9SMat Martineau 		chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
53885b155ef9SMat Martineau 		break;
53895b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP_SUCCESS:
53905b155ef9SMat Martineau 		if (result == L2CAP_MR_PEND) {
53915b155ef9SMat Martineau 			break;
53925b155ef9SMat Martineau 		} else if (test_bit(CONN_LOCAL_BUSY,
53935b155ef9SMat Martineau 				    &chan->conn_state)) {
53945b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
53955b155ef9SMat Martineau 		} else {
53965b155ef9SMat Martineau 			/* Logical link is up or moving to BR/EDR,
53975b155ef9SMat Martineau 			 * proceed with move
53985b155ef9SMat Martineau 			 */
53995b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
54005b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
54015b155ef9SMat Martineau 		}
54025b155ef9SMat Martineau 		break;
54035b155ef9SMat Martineau 	case L2CAP_MOVE_WAIT_RSP:
54045b155ef9SMat Martineau 		/* Moving to AMP */
54055b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
54065b155ef9SMat Martineau 			/* Remote is ready, send confirm immediately
54075b155ef9SMat Martineau 			 * after logical link is ready
54085b155ef9SMat Martineau 			 */
54095b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
54105b155ef9SMat Martineau 		} else {
54115b155ef9SMat Martineau 			/* Both logical link and move success
54125b155ef9SMat Martineau 			 * are required to confirm
54135b155ef9SMat Martineau 			 */
54145b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
54155b155ef9SMat Martineau 		}
54165b155ef9SMat Martineau 
54175b155ef9SMat Martineau 		/* Placeholder - get hci_chan for logical link */
54185b155ef9SMat Martineau 		if (!hchan) {
54195b155ef9SMat Martineau 			/* Logical link not available */
54205b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
54215b155ef9SMat Martineau 			break;
54225b155ef9SMat Martineau 		}
54235b155ef9SMat Martineau 
54245b155ef9SMat Martineau 		/* If the logical link is not yet connected, do not
54255b155ef9SMat Martineau 		 * send confirmation.
54265b155ef9SMat Martineau 		 */
54275b155ef9SMat Martineau 		if (hchan->state != BT_CONNECTED)
54285b155ef9SMat Martineau 			break;
54295b155ef9SMat Martineau 
54305b155ef9SMat Martineau 		/* Logical link is already ready to go */
54315b155ef9SMat Martineau 
54325b155ef9SMat Martineau 		chan->hs_hcon = hchan->conn;
54335b155ef9SMat Martineau 		chan->hs_hcon->l2cap_data = chan->conn;
54345b155ef9SMat Martineau 
54355b155ef9SMat Martineau 		if (result == L2CAP_MR_SUCCESS) {
54365b155ef9SMat Martineau 			/* Can confirm now */
54375b155ef9SMat Martineau 			l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
54385b155ef9SMat Martineau 		} else {
54395b155ef9SMat Martineau 			/* Now only need move success
54405b155ef9SMat Martineau 			 * to confirm
54415b155ef9SMat Martineau 			 */
54425b155ef9SMat Martineau 			chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
54435b155ef9SMat Martineau 		}
54445b155ef9SMat Martineau 
54455b155ef9SMat Martineau 		l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
54465b155ef9SMat Martineau 		break;
54475b155ef9SMat Martineau 	default:
54485b155ef9SMat Martineau 		/* Any other amp move state means the move failed. */
54495b155ef9SMat Martineau 		chan->move_id = chan->local_amp_id;
54505b155ef9SMat Martineau 		l2cap_move_done(chan);
54515b155ef9SMat Martineau 		l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
54525b155ef9SMat Martineau 	}
54535b155ef9SMat Martineau 
54545b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
5455d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
54565b155ef9SMat Martineau }
54575b155ef9SMat Martineau 
54585b155ef9SMat Martineau static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
54595b155ef9SMat Martineau 			    u16 result)
54605b155ef9SMat Martineau {
54615b155ef9SMat Martineau 	struct l2cap_chan *chan;
54625b155ef9SMat Martineau 
54635b155ef9SMat Martineau 	chan = l2cap_get_chan_by_ident(conn, ident);
54645b155ef9SMat Martineau 	if (!chan) {
54655b155ef9SMat Martineau 		/* Could not locate channel, icid is best guess */
54665b155ef9SMat Martineau 		l2cap_send_move_chan_cfm_icid(conn, icid);
54675b155ef9SMat Martineau 		return;
54685b155ef9SMat Martineau 	}
54695b155ef9SMat Martineau 
54705b155ef9SMat Martineau 	__clear_chan_timer(chan);
54715b155ef9SMat Martineau 
54725b155ef9SMat Martineau 	if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
54735b155ef9SMat Martineau 		if (result == L2CAP_MR_COLLISION) {
54745b155ef9SMat Martineau 			chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
54755b155ef9SMat Martineau 		} else {
54765b155ef9SMat Martineau 			/* Cleanup - cancel move */
54775b155ef9SMat Martineau 			chan->move_id = chan->local_amp_id;
54785b155ef9SMat Martineau 			l2cap_move_done(chan);
54795b155ef9SMat Martineau 		}
54805b155ef9SMat Martineau 	}
54815b155ef9SMat Martineau 
54825b155ef9SMat Martineau 	l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
54835b155ef9SMat Martineau 
54845b155ef9SMat Martineau 	l2cap_chan_unlock(chan);
5485d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
54865b155ef9SMat Martineau }
54875b155ef9SMat Martineau 
54885b155ef9SMat Martineau static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
5489ad0ac6caSAndrei Emeltchenko 				  struct l2cap_cmd_hdr *cmd,
5490ad0ac6caSAndrei Emeltchenko 				  u16 cmd_len, void *data)
54918d5a04a1SMat Martineau {
54928d5a04a1SMat Martineau 	struct l2cap_move_chan_rsp *rsp = data;
54938d5a04a1SMat Martineau 	u16 icid, result;
54948d5a04a1SMat Martineau 
54958d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
54968d5a04a1SMat Martineau 		return -EPROTO;
54978d5a04a1SMat Martineau 
54988d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
54998d5a04a1SMat Martineau 	result = le16_to_cpu(rsp->result);
55008d5a04a1SMat Martineau 
5501ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
55028d5a04a1SMat Martineau 
55035b155ef9SMat Martineau 	if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
55045b155ef9SMat Martineau 		l2cap_move_continue(conn, icid, result);
55055b155ef9SMat Martineau 	else
55065b155ef9SMat Martineau 		l2cap_move_fail(conn, cmd->ident, icid, result);
55078d5a04a1SMat Martineau 
55088d5a04a1SMat Martineau 	return 0;
55098d5a04a1SMat Martineau }
55108d5a04a1SMat Martineau 
55115f3847a4SMat Martineau static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
5512ad0ac6caSAndrei Emeltchenko 				      struct l2cap_cmd_hdr *cmd,
5513ad0ac6caSAndrei Emeltchenko 				      u16 cmd_len, void *data)
55148d5a04a1SMat Martineau {
55158d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm *cfm = data;
55165f3847a4SMat Martineau 	struct l2cap_chan *chan;
55178d5a04a1SMat Martineau 	u16 icid, result;
55188d5a04a1SMat Martineau 
55198d5a04a1SMat Martineau 	if (cmd_len != sizeof(*cfm))
55208d5a04a1SMat Martineau 		return -EPROTO;
55218d5a04a1SMat Martineau 
55228d5a04a1SMat Martineau 	icid = le16_to_cpu(cfm->icid);
55238d5a04a1SMat Martineau 	result = le16_to_cpu(cfm->result);
55248d5a04a1SMat Martineau 
5525ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
55268d5a04a1SMat Martineau 
55275f3847a4SMat Martineau 	chan = l2cap_get_chan_by_dcid(conn, icid);
55285f3847a4SMat Martineau 	if (!chan) {
55295f3847a4SMat Martineau 		/* Spec requires a response even if the icid was not found */
55308d5a04a1SMat Martineau 		l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
55315f3847a4SMat Martineau 		return 0;
55325f3847a4SMat Martineau 	}
55335f3847a4SMat Martineau 
55345f3847a4SMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
55355f3847a4SMat Martineau 		if (result == L2CAP_MC_CONFIRMED) {
55365f3847a4SMat Martineau 			chan->local_amp_id = chan->move_id;
55376ed971caSMarcel Holtmann 			if (chan->local_amp_id == AMP_ID_BREDR)
55385f3847a4SMat Martineau 				__release_logical_link(chan);
55395f3847a4SMat Martineau 		} else {
55405f3847a4SMat Martineau 			chan->move_id = chan->local_amp_id;
55415f3847a4SMat Martineau 		}
55425f3847a4SMat Martineau 
55435f3847a4SMat Martineau 		l2cap_move_done(chan);
55445f3847a4SMat Martineau 	}
55455f3847a4SMat Martineau 
55465f3847a4SMat Martineau 	l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
55475f3847a4SMat Martineau 
55485f3847a4SMat Martineau 	l2cap_chan_unlock(chan);
5549d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
55508d5a04a1SMat Martineau 
55518d5a04a1SMat Martineau 	return 0;
55528d5a04a1SMat Martineau }
55538d5a04a1SMat Martineau 
55548d5a04a1SMat Martineau static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
5555ad0ac6caSAndrei Emeltchenko 						 struct l2cap_cmd_hdr *cmd,
5556ad0ac6caSAndrei Emeltchenko 						 u16 cmd_len, void *data)
55578d5a04a1SMat Martineau {
55588d5a04a1SMat Martineau 	struct l2cap_move_chan_cfm_rsp *rsp = data;
55593fd71a0aSMat Martineau 	struct l2cap_chan *chan;
55608d5a04a1SMat Martineau 	u16 icid;
55618d5a04a1SMat Martineau 
55628d5a04a1SMat Martineau 	if (cmd_len != sizeof(*rsp))
55638d5a04a1SMat Martineau 		return -EPROTO;
55648d5a04a1SMat Martineau 
55658d5a04a1SMat Martineau 	icid = le16_to_cpu(rsp->icid);
55668d5a04a1SMat Martineau 
5567ad0ac6caSAndrei Emeltchenko 	BT_DBG("icid 0x%4.4x", icid);
55688d5a04a1SMat Martineau 
55693fd71a0aSMat Martineau 	chan = l2cap_get_chan_by_scid(conn, icid);
55703fd71a0aSMat Martineau 	if (!chan)
55713fd71a0aSMat Martineau 		return 0;
55723fd71a0aSMat Martineau 
55733fd71a0aSMat Martineau 	__clear_chan_timer(chan);
55743fd71a0aSMat Martineau 
55753fd71a0aSMat Martineau 	if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
55763fd71a0aSMat Martineau 		chan->local_amp_id = chan->move_id;
55773fd71a0aSMat Martineau 
55786ed971caSMarcel Holtmann 		if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
55793fd71a0aSMat Martineau 			__release_logical_link(chan);
55803fd71a0aSMat Martineau 
55813fd71a0aSMat Martineau 		l2cap_move_done(chan);
55823fd71a0aSMat Martineau 	}
55833fd71a0aSMat Martineau 
55843fd71a0aSMat Martineau 	l2cap_chan_unlock(chan);
5585d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
55863fd71a0aSMat Martineau 
55878d5a04a1SMat Martineau 	return 0;
55888d5a04a1SMat Martineau }
55898d5a04a1SMat Martineau 
5590de73115aSClaudio Takahasi static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
55912d792818SGustavo Padovan 					      struct l2cap_cmd_hdr *cmd,
5592203e639eSJohan Hedberg 					      u16 cmd_len, u8 *data)
5593de73115aSClaudio Takahasi {
5594de73115aSClaudio Takahasi 	struct hci_conn *hcon = conn->hcon;
5595de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_req *req;
5596de73115aSClaudio Takahasi 	struct l2cap_conn_param_update_rsp rsp;
5597203e639eSJohan Hedberg 	u16 min, max, latency, to_multiplier;
55982ce603ebSClaudio Takahasi 	int err;
5599de73115aSClaudio Takahasi 
560040bef302SJohan Hedberg 	if (hcon->role != HCI_ROLE_MASTER)
5601de73115aSClaudio Takahasi 		return -EINVAL;
5602de73115aSClaudio Takahasi 
5603de73115aSClaudio Takahasi 	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
5604de73115aSClaudio Takahasi 		return -EPROTO;
5605de73115aSClaudio Takahasi 
5606de73115aSClaudio Takahasi 	req = (struct l2cap_conn_param_update_req *) data;
5607de73115aSClaudio Takahasi 	min		= __le16_to_cpu(req->min);
5608de73115aSClaudio Takahasi 	max		= __le16_to_cpu(req->max);
5609de73115aSClaudio Takahasi 	latency		= __le16_to_cpu(req->latency);
5610de73115aSClaudio Takahasi 	to_multiplier	= __le16_to_cpu(req->to_multiplier);
5611de73115aSClaudio Takahasi 
5612de73115aSClaudio Takahasi 	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
5613de73115aSClaudio Takahasi 	       min, max, latency, to_multiplier);
5614de73115aSClaudio Takahasi 
5615de73115aSClaudio Takahasi 	memset(&rsp, 0, sizeof(rsp));
56162ce603ebSClaudio Takahasi 
5617d4905f24SAndre Guedes 	err = hci_check_conn_params(min, max, latency, to_multiplier);
56182ce603ebSClaudio Takahasi 	if (err)
5619dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
5620de73115aSClaudio Takahasi 	else
5621dcf4adbfSJoe Perches 		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
5622de73115aSClaudio Takahasi 
5623de73115aSClaudio Takahasi 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
5624de73115aSClaudio Takahasi 		       sizeof(rsp), &rsp);
5625de73115aSClaudio Takahasi 
5626ffb5a827SAndre Guedes 	if (!err) {
5627f4869e2aSJohan Hedberg 		u8 store_hint;
5628ffb5a827SAndre Guedes 
5629f4869e2aSJohan Hedberg 		store_hint = hci_le_conn_update(hcon, min, max, latency,
5630f4869e2aSJohan Hedberg 						to_multiplier);
5631f4869e2aSJohan Hedberg 		mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type,
5632f4869e2aSJohan Hedberg 				    store_hint, min, max, latency,
5633f4869e2aSJohan Hedberg 				    to_multiplier);
5634f4869e2aSJohan Hedberg 
5635ffb5a827SAndre Guedes 	}
56362ce603ebSClaudio Takahasi 
5637de73115aSClaudio Takahasi 	return 0;
5638de73115aSClaudio Takahasi }
5639de73115aSClaudio Takahasi 
5640f1496deeSJohan Hedberg static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
5641f1496deeSJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5642f1496deeSJohan Hedberg 				u8 *data)
5643f1496deeSJohan Hedberg {
5644f1496deeSJohan Hedberg 	struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
56453e64b7bdSJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
5646f1496deeSJohan Hedberg 	u16 dcid, mtu, mps, credits, result;
5647f1496deeSJohan Hedberg 	struct l2cap_chan *chan;
56483e64b7bdSJohan Hedberg 	int err, sec_level;
5649f1496deeSJohan Hedberg 
5650f1496deeSJohan Hedberg 	if (cmd_len < sizeof(*rsp))
5651f1496deeSJohan Hedberg 		return -EPROTO;
5652f1496deeSJohan Hedberg 
5653f1496deeSJohan Hedberg 	dcid    = __le16_to_cpu(rsp->dcid);
5654f1496deeSJohan Hedberg 	mtu     = __le16_to_cpu(rsp->mtu);
5655f1496deeSJohan Hedberg 	mps     = __le16_to_cpu(rsp->mps);
5656f1496deeSJohan Hedberg 	credits = __le16_to_cpu(rsp->credits);
5657f1496deeSJohan Hedberg 	result  = __le16_to_cpu(rsp->result);
5658f1496deeSJohan Hedberg 
5659571f7390SMallikarjun Phulari 	if (result == L2CAP_CR_LE_SUCCESS && (mtu < 23 || mps < 23 ||
566040624183SJohan Hedberg 					   dcid < L2CAP_CID_DYN_START ||
566140624183SJohan Hedberg 					   dcid > L2CAP_CID_LE_DYN_END))
5662f1496deeSJohan Hedberg 		return -EPROTO;
5663f1496deeSJohan Hedberg 
5664f1496deeSJohan Hedberg 	BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
5665f1496deeSJohan Hedberg 	       dcid, mtu, mps, credits, result);
5666f1496deeSJohan Hedberg 
5667f1496deeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
5668f1496deeSJohan Hedberg 
5669f1496deeSJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
5670f1496deeSJohan Hedberg 	if (!chan) {
5671f1496deeSJohan Hedberg 		err = -EBADSLT;
5672f1496deeSJohan Hedberg 		goto unlock;
5673f1496deeSJohan Hedberg 	}
5674f1496deeSJohan Hedberg 
5675f1496deeSJohan Hedberg 	err = 0;
5676f1496deeSJohan Hedberg 
5677f1496deeSJohan Hedberg 	l2cap_chan_lock(chan);
5678f1496deeSJohan Hedberg 
5679f1496deeSJohan Hedberg 	switch (result) {
5680571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_SUCCESS:
568140624183SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, dcid)) {
568240624183SJohan Hedberg 			err = -EBADSLT;
568340624183SJohan Hedberg 			break;
568440624183SJohan Hedberg 		}
568540624183SJohan Hedberg 
5686f1496deeSJohan Hedberg 		chan->ident = 0;
5687f1496deeSJohan Hedberg 		chan->dcid = dcid;
5688f1496deeSJohan Hedberg 		chan->omtu = mtu;
5689f1496deeSJohan Hedberg 		chan->remote_mps = mps;
56900cd75f7eSJohan Hedberg 		chan->tx_credits = credits;
5691f1496deeSJohan Hedberg 		l2cap_chan_ready(chan);
5692f1496deeSJohan Hedberg 		break;
5693f1496deeSJohan Hedberg 
5694571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_AUTHENTICATION:
5695571f7390SMallikarjun Phulari 	case L2CAP_CR_LE_ENCRYPTION:
56963e64b7bdSJohan Hedberg 		/* If we already have MITM protection we can't do
56973e64b7bdSJohan Hedberg 		 * anything.
56983e64b7bdSJohan Hedberg 		 */
56993e64b7bdSJohan Hedberg 		if (hcon->sec_level > BT_SECURITY_MEDIUM) {
57003e64b7bdSJohan Hedberg 			l2cap_chan_del(chan, ECONNREFUSED);
57013e64b7bdSJohan Hedberg 			break;
57023e64b7bdSJohan Hedberg 		}
57033e64b7bdSJohan Hedberg 
57043e64b7bdSJohan Hedberg 		sec_level = hcon->sec_level + 1;
57053e64b7bdSJohan Hedberg 		if (chan->sec_level < sec_level)
57063e64b7bdSJohan Hedberg 			chan->sec_level = sec_level;
57073e64b7bdSJohan Hedberg 
57083e64b7bdSJohan Hedberg 		/* We'll need to send a new Connect Request */
57093e64b7bdSJohan Hedberg 		clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
57103e64b7bdSJohan Hedberg 
57113e64b7bdSJohan Hedberg 		smp_conn_security(hcon, chan->sec_level);
57123e64b7bdSJohan Hedberg 		break;
57133e64b7bdSJohan Hedberg 
5714f1496deeSJohan Hedberg 	default:
5715f1496deeSJohan Hedberg 		l2cap_chan_del(chan, ECONNREFUSED);
5716f1496deeSJohan Hedberg 		break;
5717f1496deeSJohan Hedberg 	}
5718f1496deeSJohan Hedberg 
5719f1496deeSJohan Hedberg 	l2cap_chan_unlock(chan);
5720f1496deeSJohan Hedberg 
5721f1496deeSJohan Hedberg unlock:
5722f1496deeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5723f1496deeSJohan Hedberg 
5724f1496deeSJohan Hedberg 	return err;
5725f1496deeSJohan Hedberg }
5726f1496deeSJohan Hedberg 
57273300d9a9SClaudio Takahasi static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
57282d792818SGustavo Padovan 				      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
57292d792818SGustavo Padovan 				      u8 *data)
57303300d9a9SClaudio Takahasi {
57313300d9a9SClaudio Takahasi 	int err = 0;
57323300d9a9SClaudio Takahasi 
57333300d9a9SClaudio Takahasi 	switch (cmd->code) {
57343300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
5735cb3b3152SJohan Hedberg 		l2cap_command_rej(conn, cmd, cmd_len, data);
57363300d9a9SClaudio Takahasi 		break;
57373300d9a9SClaudio Takahasi 
57383300d9a9SClaudio Takahasi 	case L2CAP_CONN_REQ:
5739cb3b3152SJohan Hedberg 		err = l2cap_connect_req(conn, cmd, cmd_len, data);
57403300d9a9SClaudio Takahasi 		break;
57413300d9a9SClaudio Takahasi 
57423300d9a9SClaudio Takahasi 	case L2CAP_CONN_RSP:
5743f5a2598dSMat Martineau 	case L2CAP_CREATE_CHAN_RSP:
57449245e737SJohan Hedberg 		l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
57453300d9a9SClaudio Takahasi 		break;
57463300d9a9SClaudio Takahasi 
57473300d9a9SClaudio Takahasi 	case L2CAP_CONF_REQ:
57483300d9a9SClaudio Takahasi 		err = l2cap_config_req(conn, cmd, cmd_len, data);
57493300d9a9SClaudio Takahasi 		break;
57503300d9a9SClaudio Takahasi 
57513300d9a9SClaudio Takahasi 	case L2CAP_CONF_RSP:
57529245e737SJohan Hedberg 		l2cap_config_rsp(conn, cmd, cmd_len, data);
57533300d9a9SClaudio Takahasi 		break;
57543300d9a9SClaudio Takahasi 
57553300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_REQ:
5756cb3b3152SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
57573300d9a9SClaudio Takahasi 		break;
57583300d9a9SClaudio Takahasi 
57593300d9a9SClaudio Takahasi 	case L2CAP_DISCONN_RSP:
57609245e737SJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
57613300d9a9SClaudio Takahasi 		break;
57623300d9a9SClaudio Takahasi 
57633300d9a9SClaudio Takahasi 	case L2CAP_ECHO_REQ:
57643300d9a9SClaudio Takahasi 		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
57653300d9a9SClaudio Takahasi 		break;
57663300d9a9SClaudio Takahasi 
57673300d9a9SClaudio Takahasi 	case L2CAP_ECHO_RSP:
57683300d9a9SClaudio Takahasi 		break;
57693300d9a9SClaudio Takahasi 
57703300d9a9SClaudio Takahasi 	case L2CAP_INFO_REQ:
5771cb3b3152SJohan Hedberg 		err = l2cap_information_req(conn, cmd, cmd_len, data);
57723300d9a9SClaudio Takahasi 		break;
57733300d9a9SClaudio Takahasi 
57743300d9a9SClaudio Takahasi 	case L2CAP_INFO_RSP:
57759245e737SJohan Hedberg 		l2cap_information_rsp(conn, cmd, cmd_len, data);
57763300d9a9SClaudio Takahasi 		break;
57773300d9a9SClaudio Takahasi 
5778f94ff6ffSMat Martineau 	case L2CAP_CREATE_CHAN_REQ:
5779f94ff6ffSMat Martineau 		err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
5780f94ff6ffSMat Martineau 		break;
5781f94ff6ffSMat Martineau 
57828d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_REQ:
57838d5a04a1SMat Martineau 		err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
57848d5a04a1SMat Martineau 		break;
57858d5a04a1SMat Martineau 
57868d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_RSP:
57879245e737SJohan Hedberg 		l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
57888d5a04a1SMat Martineau 		break;
57898d5a04a1SMat Martineau 
57908d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM:
57918d5a04a1SMat Martineau 		err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
57928d5a04a1SMat Martineau 		break;
57938d5a04a1SMat Martineau 
57948d5a04a1SMat Martineau 	case L2CAP_MOVE_CHAN_CFM_RSP:
57959245e737SJohan Hedberg 		l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
57968d5a04a1SMat Martineau 		break;
57978d5a04a1SMat Martineau 
57983300d9a9SClaudio Takahasi 	default:
57993300d9a9SClaudio Takahasi 		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
58003300d9a9SClaudio Takahasi 		err = -EINVAL;
58013300d9a9SClaudio Takahasi 		break;
58023300d9a9SClaudio Takahasi 	}
58033300d9a9SClaudio Takahasi 
58043300d9a9SClaudio Takahasi 	return err;
58053300d9a9SClaudio Takahasi }
58063300d9a9SClaudio Takahasi 
580727e2d4c8SJohan Hedberg static int l2cap_le_connect_req(struct l2cap_conn *conn,
580827e2d4c8SJohan Hedberg 				struct l2cap_cmd_hdr *cmd, u16 cmd_len,
580927e2d4c8SJohan Hedberg 				u8 *data)
581027e2d4c8SJohan Hedberg {
581127e2d4c8SJohan Hedberg 	struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
581227e2d4c8SJohan Hedberg 	struct l2cap_le_conn_rsp rsp;
581327e2d4c8SJohan Hedberg 	struct l2cap_chan *chan, *pchan;
58140cd75f7eSJohan Hedberg 	u16 dcid, scid, credits, mtu, mps;
581527e2d4c8SJohan Hedberg 	__le16 psm;
581627e2d4c8SJohan Hedberg 	u8 result;
581727e2d4c8SJohan Hedberg 
581827e2d4c8SJohan Hedberg 	if (cmd_len != sizeof(*req))
581927e2d4c8SJohan Hedberg 		return -EPROTO;
582027e2d4c8SJohan Hedberg 
582127e2d4c8SJohan Hedberg 	scid = __le16_to_cpu(req->scid);
582227e2d4c8SJohan Hedberg 	mtu  = __le16_to_cpu(req->mtu);
582327e2d4c8SJohan Hedberg 	mps  = __le16_to_cpu(req->mps);
582427e2d4c8SJohan Hedberg 	psm  = req->psm;
582527e2d4c8SJohan Hedberg 	dcid = 0;
58260cd75f7eSJohan Hedberg 	credits = 0;
582727e2d4c8SJohan Hedberg 
582827e2d4c8SJohan Hedberg 	if (mtu < 23 || mps < 23)
582927e2d4c8SJohan Hedberg 		return -EPROTO;
583027e2d4c8SJohan Hedberg 
583127e2d4c8SJohan Hedberg 	BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
583227e2d4c8SJohan Hedberg 	       scid, mtu, mps);
583327e2d4c8SJohan Hedberg 
5834711f8c3fSLuiz Augusto von Dentz 	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
5835711f8c3fSLuiz Augusto von Dentz 	 * page 1059:
5836711f8c3fSLuiz Augusto von Dentz 	 *
5837711f8c3fSLuiz Augusto von Dentz 	 * Valid range: 0x0001-0x00ff
5838711f8c3fSLuiz Augusto von Dentz 	 *
5839711f8c3fSLuiz Augusto von Dentz 	 * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
5840711f8c3fSLuiz Augusto von Dentz 	 */
5841711f8c3fSLuiz Augusto von Dentz 	if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
5842711f8c3fSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
5843711f8c3fSLuiz Augusto von Dentz 		chan = NULL;
5844711f8c3fSLuiz Augusto von Dentz 		goto response;
5845711f8c3fSLuiz Augusto von Dentz 	}
5846711f8c3fSLuiz Augusto von Dentz 
584727e2d4c8SJohan Hedberg 	/* Check if we have socket listening on psm */
584827e2d4c8SJohan Hedberg 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
584927e2d4c8SJohan Hedberg 					 &conn->hcon->dst, LE_LINK);
585027e2d4c8SJohan Hedberg 	if (!pchan) {
5851571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_BAD_PSM;
585227e2d4c8SJohan Hedberg 		chan = NULL;
585327e2d4c8SJohan Hedberg 		goto response;
585427e2d4c8SJohan Hedberg 	}
585527e2d4c8SJohan Hedberg 
585627e2d4c8SJohan Hedberg 	mutex_lock(&conn->chan_lock);
585727e2d4c8SJohan Hedberg 	l2cap_chan_lock(pchan);
585827e2d4c8SJohan Hedberg 
585935dc6f83SJohan Hedberg 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
586035dc6f83SJohan Hedberg 				     SMP_ALLOW_STK)) {
5861571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_AUTHENTICATION;
586227e2d4c8SJohan Hedberg 		chan = NULL;
586327e2d4c8SJohan Hedberg 		goto response_unlock;
586427e2d4c8SJohan Hedberg 	}
586527e2d4c8SJohan Hedberg 
58668a7889ccSJohan Hedberg 	/* Check for valid dynamic CID range */
58678a7889ccSJohan Hedberg 	if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
5868571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_INVALID_SCID;
58698a7889ccSJohan Hedberg 		chan = NULL;
58708a7889ccSJohan Hedberg 		goto response_unlock;
58718a7889ccSJohan Hedberg 	}
58728a7889ccSJohan Hedberg 
587327e2d4c8SJohan Hedberg 	/* Check if we already have channel with that dcid */
587427e2d4c8SJohan Hedberg 	if (__l2cap_get_chan_by_dcid(conn, scid)) {
5875571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SCID_IN_USE;
587627e2d4c8SJohan Hedberg 		chan = NULL;
587727e2d4c8SJohan Hedberg 		goto response_unlock;
587827e2d4c8SJohan Hedberg 	}
587927e2d4c8SJohan Hedberg 
588027e2d4c8SJohan Hedberg 	chan = pchan->ops->new_connection(pchan);
588127e2d4c8SJohan Hedberg 	if (!chan) {
5882571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_NO_MEM;
588327e2d4c8SJohan Hedberg 		goto response_unlock;
588427e2d4c8SJohan Hedberg 	}
588527e2d4c8SJohan Hedberg 
588627e2d4c8SJohan Hedberg 	bacpy(&chan->src, &conn->hcon->src);
588727e2d4c8SJohan Hedberg 	bacpy(&chan->dst, &conn->hcon->dst);
5888a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(conn->hcon);
5889a250e048SJohan Hedberg 	chan->dst_type = bdaddr_dst_type(conn->hcon);
589027e2d4c8SJohan Hedberg 	chan->psm  = psm;
589127e2d4c8SJohan Hedberg 	chan->dcid = scid;
589227e2d4c8SJohan Hedberg 	chan->omtu = mtu;
589327e2d4c8SJohan Hedberg 	chan->remote_mps = mps;
589427e2d4c8SJohan Hedberg 
589527e2d4c8SJohan Hedberg 	__l2cap_chan_add(conn, chan);
5896fe149310SLuiz Augusto von Dentz 
5897ba8f5289SLuiz Augusto von Dentz 	l2cap_le_flowctl_init(chan, __le16_to_cpu(req->credits));
5898fe149310SLuiz Augusto von Dentz 
589927e2d4c8SJohan Hedberg 	dcid = chan->scid;
59000cd75f7eSJohan Hedberg 	credits = chan->rx_credits;
590127e2d4c8SJohan Hedberg 
590227e2d4c8SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
590327e2d4c8SJohan Hedberg 
590427e2d4c8SJohan Hedberg 	chan->ident = cmd->ident;
590527e2d4c8SJohan Hedberg 
590627e2d4c8SJohan Hedberg 	if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
590727e2d4c8SJohan Hedberg 		l2cap_state_change(chan, BT_CONNECT2);
5908434714dcSJohan Hedberg 		/* The following result value is actually not defined
5909434714dcSJohan Hedberg 		 * for LE CoC but we use it to let the function know
5910434714dcSJohan Hedberg 		 * that it should bail out after doing its cleanup
5911434714dcSJohan Hedberg 		 * instead of sending a response.
5912434714dcSJohan Hedberg 		 */
591327e2d4c8SJohan Hedberg 		result = L2CAP_CR_PEND;
591427e2d4c8SJohan Hedberg 		chan->ops->defer(chan);
591527e2d4c8SJohan Hedberg 	} else {
591627e2d4c8SJohan Hedberg 		l2cap_chan_ready(chan);
5917571f7390SMallikarjun Phulari 		result = L2CAP_CR_LE_SUCCESS;
591827e2d4c8SJohan Hedberg 	}
591927e2d4c8SJohan Hedberg 
592027e2d4c8SJohan Hedberg response_unlock:
592127e2d4c8SJohan Hedberg 	l2cap_chan_unlock(pchan);
592227e2d4c8SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
5923a24cce14SJohan Hedberg 	l2cap_chan_put(pchan);
592427e2d4c8SJohan Hedberg 
592527e2d4c8SJohan Hedberg 	if (result == L2CAP_CR_PEND)
592627e2d4c8SJohan Hedberg 		return 0;
592727e2d4c8SJohan Hedberg 
592827e2d4c8SJohan Hedberg response:
592927e2d4c8SJohan Hedberg 	if (chan) {
593027e2d4c8SJohan Hedberg 		rsp.mtu = cpu_to_le16(chan->imtu);
59313916aed8SJohan Hedberg 		rsp.mps = cpu_to_le16(chan->mps);
593227e2d4c8SJohan Hedberg 	} else {
593327e2d4c8SJohan Hedberg 		rsp.mtu = 0;
593427e2d4c8SJohan Hedberg 		rsp.mps = 0;
593527e2d4c8SJohan Hedberg 	}
593627e2d4c8SJohan Hedberg 
593727e2d4c8SJohan Hedberg 	rsp.dcid    = cpu_to_le16(dcid);
59380cd75f7eSJohan Hedberg 	rsp.credits = cpu_to_le16(credits);
593927e2d4c8SJohan Hedberg 	rsp.result  = cpu_to_le16(result);
594027e2d4c8SJohan Hedberg 
594127e2d4c8SJohan Hedberg 	l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
594227e2d4c8SJohan Hedberg 
594327e2d4c8SJohan Hedberg 	return 0;
594427e2d4c8SJohan Hedberg }
594527e2d4c8SJohan Hedberg 
5946fad5fc89SJohan Hedberg static inline int l2cap_le_credits(struct l2cap_conn *conn,
5947fad5fc89SJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
5948fad5fc89SJohan Hedberg 				   u8 *data)
5949fad5fc89SJohan Hedberg {
5950fad5fc89SJohan Hedberg 	struct l2cap_le_credits *pkt;
5951fad5fc89SJohan Hedberg 	struct l2cap_chan *chan;
59520f1bfe4eSJohan Hedberg 	u16 cid, credits, max_credits;
5953fad5fc89SJohan Hedberg 
5954fad5fc89SJohan Hedberg 	if (cmd_len != sizeof(*pkt))
5955fad5fc89SJohan Hedberg 		return -EPROTO;
5956fad5fc89SJohan Hedberg 
5957fad5fc89SJohan Hedberg 	pkt = (struct l2cap_le_credits *) data;
5958fad5fc89SJohan Hedberg 	cid	= __le16_to_cpu(pkt->cid);
5959fad5fc89SJohan Hedberg 	credits	= __le16_to_cpu(pkt->credits);
5960fad5fc89SJohan Hedberg 
5961fad5fc89SJohan Hedberg 	BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
5962fad5fc89SJohan Hedberg 
5963fad5fc89SJohan Hedberg 	chan = l2cap_get_chan_by_dcid(conn, cid);
5964fad5fc89SJohan Hedberg 	if (!chan)
5965fad5fc89SJohan Hedberg 		return -EBADSLT;
5966fad5fc89SJohan Hedberg 
59670f1bfe4eSJohan Hedberg 	max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
59680f1bfe4eSJohan Hedberg 	if (credits > max_credits) {
59690f1bfe4eSJohan Hedberg 		BT_ERR("LE credits overflow");
59700f1bfe4eSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
59710f1bfe4eSJohan Hedberg 
59720f1bfe4eSJohan Hedberg 		/* Return 0 so that we don't trigger an unnecessary
59730f1bfe4eSJohan Hedberg 		 * command reject packet.
59740f1bfe4eSJohan Hedberg 		 */
5975d0be8347SLuiz Augusto von Dentz 		goto unlock;
59760f1bfe4eSJohan Hedberg 	}
59770f1bfe4eSJohan Hedberg 
5978fad5fc89SJohan Hedberg 	chan->tx_credits += credits;
5979fad5fc89SJohan Hedberg 
59808a505b7fSLuiz Augusto von Dentz 	/* Resume sending */
59818a505b7fSLuiz Augusto von Dentz 	l2cap_le_flowctl_send(chan);
5982fad5fc89SJohan Hedberg 
5983fad5fc89SJohan Hedberg 	if (chan->tx_credits)
5984fad5fc89SJohan Hedberg 		chan->ops->resume(chan);
5985fad5fc89SJohan Hedberg 
5986d0be8347SLuiz Augusto von Dentz unlock:
5987fad5fc89SJohan Hedberg 	l2cap_chan_unlock(chan);
5988d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
5989fad5fc89SJohan Hedberg 
5990fad5fc89SJohan Hedberg 	return 0;
5991fad5fc89SJohan Hedberg }
5992fad5fc89SJohan Hedberg 
599315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
599415f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
599515f02b91SLuiz Augusto von Dentz 				       u8 *data)
599615f02b91SLuiz Augusto von Dentz {
599715f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_req *req = (void *) data;
599815f02b91SLuiz Augusto von Dentz 	struct {
599915f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_conn_rsp rsp;
60007cf3b1ddSLuiz Augusto von Dentz 		__le16 dcid[L2CAP_ECRED_MAX_CID];
600115f02b91SLuiz Augusto von Dentz 	} __packed pdu;
600215f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *pchan;
6003965995b7SYueHaibing 	u16 mtu, mps;
600415f02b91SLuiz Augusto von Dentz 	__le16 psm;
600515f02b91SLuiz Augusto von Dentz 	u8 result, len = 0;
600615f02b91SLuiz Augusto von Dentz 	int i, num_scid;
600715f02b91SLuiz Augusto von Dentz 	bool defer = false;
600815f02b91SLuiz Augusto von Dentz 
60094be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
60104be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
60114be5ca67SLuiz Augusto von Dentz 
601269d67b46SKonstantin Forostyan 	if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
601315f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
601415f02b91SLuiz Augusto von Dentz 		goto response;
601515f02b91SLuiz Augusto von Dentz 	}
601615f02b91SLuiz Augusto von Dentz 
60177cf3b1ddSLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
60187cf3b1ddSLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
60197cf3b1ddSLuiz Augusto von Dentz 
60207cf3b1ddSLuiz Augusto von Dentz 	if (num_scid > ARRAY_SIZE(pdu.dcid)) {
60217cf3b1ddSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
60227cf3b1ddSLuiz Augusto von Dentz 		goto response;
60237cf3b1ddSLuiz Augusto von Dentz 	}
60247cf3b1ddSLuiz Augusto von Dentz 
602515f02b91SLuiz Augusto von Dentz 	mtu  = __le16_to_cpu(req->mtu);
602615f02b91SLuiz Augusto von Dentz 	mps  = __le16_to_cpu(req->mps);
602715f02b91SLuiz Augusto von Dentz 
602815f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU || mps < L2CAP_ECRED_MIN_MPS) {
602915f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_UNACCEPT_PARAMS;
603015f02b91SLuiz Augusto von Dentz 		goto response;
603115f02b91SLuiz Augusto von Dentz 	}
603215f02b91SLuiz Augusto von Dentz 
603315f02b91SLuiz Augusto von Dentz 	psm  = req->psm;
603415f02b91SLuiz Augusto von Dentz 
6035711f8c3fSLuiz Augusto von Dentz 	/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
6036711f8c3fSLuiz Augusto von Dentz 	 * page 1059:
6037711f8c3fSLuiz Augusto von Dentz 	 *
6038711f8c3fSLuiz Augusto von Dentz 	 * Valid range: 0x0001-0x00ff
6039711f8c3fSLuiz Augusto von Dentz 	 *
6040711f8c3fSLuiz Augusto von Dentz 	 * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
6041711f8c3fSLuiz Augusto von Dentz 	 */
6042711f8c3fSLuiz Augusto von Dentz 	if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
6043711f8c3fSLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
6044711f8c3fSLuiz Augusto von Dentz 		goto response;
6045711f8c3fSLuiz Augusto von Dentz 	}
6046711f8c3fSLuiz Augusto von Dentz 
604715f02b91SLuiz Augusto von Dentz 	BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
604815f02b91SLuiz Augusto von Dentz 
604915f02b91SLuiz Augusto von Dentz 	memset(&pdu, 0, sizeof(pdu));
605015f02b91SLuiz Augusto von Dentz 
605115f02b91SLuiz Augusto von Dentz 	/* Check if we have socket listening on psm */
605215f02b91SLuiz Augusto von Dentz 	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
605315f02b91SLuiz Augusto von Dentz 					 &conn->hcon->dst, LE_LINK);
605415f02b91SLuiz Augusto von Dentz 	if (!pchan) {
605515f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_BAD_PSM;
605615f02b91SLuiz Augusto von Dentz 		goto response;
605715f02b91SLuiz Augusto von Dentz 	}
605815f02b91SLuiz Augusto von Dentz 
605915f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
606015f02b91SLuiz Augusto von Dentz 	l2cap_chan_lock(pchan);
606115f02b91SLuiz Augusto von Dentz 
606215f02b91SLuiz Augusto von Dentz 	if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
606315f02b91SLuiz Augusto von Dentz 				     SMP_ALLOW_STK)) {
606415f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_AUTHENTICATION;
606515f02b91SLuiz Augusto von Dentz 		goto unlock;
606615f02b91SLuiz Augusto von Dentz 	}
606715f02b91SLuiz Augusto von Dentz 
606815f02b91SLuiz Augusto von Dentz 	result = L2CAP_CR_LE_SUCCESS;
606915f02b91SLuiz Augusto von Dentz 
607015f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
607115f02b91SLuiz Augusto von Dentz 		u16 scid = __le16_to_cpu(req->scid[i]);
607215f02b91SLuiz Augusto von Dentz 
607315f02b91SLuiz Augusto von Dentz 		BT_DBG("scid[%d] 0x%4.4x", i, scid);
607415f02b91SLuiz Augusto von Dentz 
607515f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = 0x0000;
607615f02b91SLuiz Augusto von Dentz 		len += sizeof(*pdu.dcid);
607715f02b91SLuiz Augusto von Dentz 
607815f02b91SLuiz Augusto von Dentz 		/* Check for valid dynamic CID range */
607915f02b91SLuiz Augusto von Dentz 		if (scid < L2CAP_CID_DYN_START || scid > L2CAP_CID_LE_DYN_END) {
608015f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_INVALID_SCID;
608115f02b91SLuiz Augusto von Dentz 			continue;
608215f02b91SLuiz Augusto von Dentz 		}
608315f02b91SLuiz Augusto von Dentz 
608415f02b91SLuiz Augusto von Dentz 		/* Check if we already have channel with that dcid */
608515f02b91SLuiz Augusto von Dentz 		if (__l2cap_get_chan_by_dcid(conn, scid)) {
608615f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_SCID_IN_USE;
608715f02b91SLuiz Augusto von Dentz 			continue;
608815f02b91SLuiz Augusto von Dentz 		}
608915f02b91SLuiz Augusto von Dentz 
609015f02b91SLuiz Augusto von Dentz 		chan = pchan->ops->new_connection(pchan);
609115f02b91SLuiz Augusto von Dentz 		if (!chan) {
609215f02b91SLuiz Augusto von Dentz 			result = L2CAP_CR_LE_NO_MEM;
609315f02b91SLuiz Augusto von Dentz 			continue;
609415f02b91SLuiz Augusto von Dentz 		}
609515f02b91SLuiz Augusto von Dentz 
609615f02b91SLuiz Augusto von Dentz 		bacpy(&chan->src, &conn->hcon->src);
609715f02b91SLuiz Augusto von Dentz 		bacpy(&chan->dst, &conn->hcon->dst);
609815f02b91SLuiz Augusto von Dentz 		chan->src_type = bdaddr_src_type(conn->hcon);
609915f02b91SLuiz Augusto von Dentz 		chan->dst_type = bdaddr_dst_type(conn->hcon);
610015f02b91SLuiz Augusto von Dentz 		chan->psm  = psm;
610115f02b91SLuiz Augusto von Dentz 		chan->dcid = scid;
610215f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
610315f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
610415f02b91SLuiz Augusto von Dentz 
610515f02b91SLuiz Augusto von Dentz 		__l2cap_chan_add(conn, chan);
610615f02b91SLuiz Augusto von Dentz 
610715f02b91SLuiz Augusto von Dentz 		l2cap_ecred_init(chan, __le16_to_cpu(req->credits));
610815f02b91SLuiz Augusto von Dentz 
610915f02b91SLuiz Augusto von Dentz 		/* Init response */
611015f02b91SLuiz Augusto von Dentz 		if (!pdu.rsp.credits) {
611115f02b91SLuiz Augusto von Dentz 			pdu.rsp.mtu = cpu_to_le16(chan->imtu);
611215f02b91SLuiz Augusto von Dentz 			pdu.rsp.mps = cpu_to_le16(chan->mps);
611315f02b91SLuiz Augusto von Dentz 			pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
611415f02b91SLuiz Augusto von Dentz 		}
611515f02b91SLuiz Augusto von Dentz 
611615f02b91SLuiz Augusto von Dentz 		pdu.dcid[i] = cpu_to_le16(chan->scid);
611715f02b91SLuiz Augusto von Dentz 
611815f02b91SLuiz Augusto von Dentz 		__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
611915f02b91SLuiz Augusto von Dentz 
612015f02b91SLuiz Augusto von Dentz 		chan->ident = cmd->ident;
6121*9aa9d947SLuiz Augusto von Dentz 		chan->mode = L2CAP_MODE_EXT_FLOWCTL;
612215f02b91SLuiz Augusto von Dentz 
612315f02b91SLuiz Augusto von Dentz 		if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
612415f02b91SLuiz Augusto von Dentz 			l2cap_state_change(chan, BT_CONNECT2);
612515f02b91SLuiz Augusto von Dentz 			defer = true;
612615f02b91SLuiz Augusto von Dentz 			chan->ops->defer(chan);
612715f02b91SLuiz Augusto von Dentz 		} else {
612815f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
612915f02b91SLuiz Augusto von Dentz 		}
613015f02b91SLuiz Augusto von Dentz 	}
613115f02b91SLuiz Augusto von Dentz 
613215f02b91SLuiz Augusto von Dentz unlock:
613315f02b91SLuiz Augusto von Dentz 	l2cap_chan_unlock(pchan);
613415f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
613515f02b91SLuiz Augusto von Dentz 	l2cap_chan_put(pchan);
613615f02b91SLuiz Augusto von Dentz 
613715f02b91SLuiz Augusto von Dentz response:
613815f02b91SLuiz Augusto von Dentz 	pdu.rsp.result = cpu_to_le16(result);
613915f02b91SLuiz Augusto von Dentz 
614015f02b91SLuiz Augusto von Dentz 	if (defer)
614115f02b91SLuiz Augusto von Dentz 		return 0;
614215f02b91SLuiz Augusto von Dentz 
614315f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_CONN_RSP,
614415f02b91SLuiz Augusto von Dentz 		       sizeof(pdu.rsp) + len, &pdu);
614515f02b91SLuiz Augusto von Dentz 
614615f02b91SLuiz Augusto von Dentz 	return 0;
614715f02b91SLuiz Augusto von Dentz }
614815f02b91SLuiz Augusto von Dentz 
614915f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
615015f02b91SLuiz Augusto von Dentz 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
615115f02b91SLuiz Augusto von Dentz 				       u8 *data)
615215f02b91SLuiz Augusto von Dentz {
615315f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
615415f02b91SLuiz Augusto von Dentz 	struct hci_conn *hcon = conn->hcon;
615515f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, credits, result;
6156de895b43SLuiz Augusto von Dentz 	struct l2cap_chan *chan, *tmp;
615715f02b91SLuiz Augusto von Dentz 	int err = 0, sec_level;
615815f02b91SLuiz Augusto von Dentz 	int i = 0;
615915f02b91SLuiz Augusto von Dentz 
616015f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
616115f02b91SLuiz Augusto von Dentz 		return -EPROTO;
616215f02b91SLuiz Augusto von Dentz 
616315f02b91SLuiz Augusto von Dentz 	mtu     = __le16_to_cpu(rsp->mtu);
616415f02b91SLuiz Augusto von Dentz 	mps     = __le16_to_cpu(rsp->mps);
616515f02b91SLuiz Augusto von Dentz 	credits = __le16_to_cpu(rsp->credits);
616615f02b91SLuiz Augusto von Dentz 	result  = __le16_to_cpu(rsp->result);
616715f02b91SLuiz Augusto von Dentz 
616815f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u credits %u result 0x%4.4x", mtu, mps, credits,
616915f02b91SLuiz Augusto von Dentz 	       result);
617015f02b91SLuiz Augusto von Dentz 
617115f02b91SLuiz Augusto von Dentz 	mutex_lock(&conn->chan_lock);
617215f02b91SLuiz Augusto von Dentz 
617315f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*rsp);
617415f02b91SLuiz Augusto von Dentz 
6175de895b43SLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
617615f02b91SLuiz Augusto von Dentz 		u16 dcid;
617715f02b91SLuiz Augusto von Dentz 
617815f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident ||
617915f02b91SLuiz Augusto von Dentz 		    chan->mode != L2CAP_MODE_EXT_FLOWCTL ||
618015f02b91SLuiz Augusto von Dentz 		    chan->state == BT_CONNECTED)
618115f02b91SLuiz Augusto von Dentz 			continue;
618215f02b91SLuiz Augusto von Dentz 
618315f02b91SLuiz Augusto von Dentz 		l2cap_chan_lock(chan);
618415f02b91SLuiz Augusto von Dentz 
618515f02b91SLuiz Augusto von Dentz 		/* Check that there is a dcid for each pending channel */
618615f02b91SLuiz Augusto von Dentz 		if (cmd_len < sizeof(dcid)) {
618715f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
618815f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
618915f02b91SLuiz Augusto von Dentz 			continue;
619015f02b91SLuiz Augusto von Dentz 		}
619115f02b91SLuiz Augusto von Dentz 
619215f02b91SLuiz Augusto von Dentz 		dcid = __le16_to_cpu(rsp->dcid[i++]);
619315f02b91SLuiz Augusto von Dentz 		cmd_len -= sizeof(u16);
619415f02b91SLuiz Augusto von Dentz 
619515f02b91SLuiz Augusto von Dentz 		BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
619615f02b91SLuiz Augusto von Dentz 
619715f02b91SLuiz Augusto von Dentz 		/* Check if dcid is already in use */
619815f02b91SLuiz Augusto von Dentz 		if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
619915f02b91SLuiz Augusto von Dentz 			/* If a device receives a
620015f02b91SLuiz Augusto von Dentz 			 * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
620115f02b91SLuiz Augusto von Dentz 			 * already-assigned Destination CID, then both the
620215f02b91SLuiz Augusto von Dentz 			 * original channel and the new channel shall be
620315f02b91SLuiz Augusto von Dentz 			 * immediately discarded and not used.
620415f02b91SLuiz Augusto von Dentz 			 */
620515f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
620615f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
620715f02b91SLuiz Augusto von Dentz 			chan = __l2cap_get_chan_by_dcid(conn, dcid);
620815f02b91SLuiz Augusto von Dentz 			l2cap_chan_lock(chan);
620915f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNRESET);
621015f02b91SLuiz Augusto von Dentz 			l2cap_chan_unlock(chan);
621115f02b91SLuiz Augusto von Dentz 			continue;
621215f02b91SLuiz Augusto von Dentz 		}
621315f02b91SLuiz Augusto von Dentz 
621415f02b91SLuiz Augusto von Dentz 		switch (result) {
621515f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_AUTHENTICATION:
621615f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_ENCRYPTION:
621715f02b91SLuiz Augusto von Dentz 			/* If we already have MITM protection we can't do
621815f02b91SLuiz Augusto von Dentz 			 * anything.
621915f02b91SLuiz Augusto von Dentz 			 */
622015f02b91SLuiz Augusto von Dentz 			if (hcon->sec_level > BT_SECURITY_MEDIUM) {
622115f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
622215f02b91SLuiz Augusto von Dentz 				break;
622315f02b91SLuiz Augusto von Dentz 			}
622415f02b91SLuiz Augusto von Dentz 
622515f02b91SLuiz Augusto von Dentz 			sec_level = hcon->sec_level + 1;
622615f02b91SLuiz Augusto von Dentz 			if (chan->sec_level < sec_level)
622715f02b91SLuiz Augusto von Dentz 				chan->sec_level = sec_level;
622815f02b91SLuiz Augusto von Dentz 
622915f02b91SLuiz Augusto von Dentz 			/* We'll need to send a new Connect Request */
623015f02b91SLuiz Augusto von Dentz 			clear_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags);
623115f02b91SLuiz Augusto von Dentz 
623215f02b91SLuiz Augusto von Dentz 			smp_conn_security(hcon, chan->sec_level);
623315f02b91SLuiz Augusto von Dentz 			break;
623415f02b91SLuiz Augusto von Dentz 
623515f02b91SLuiz Augusto von Dentz 		case L2CAP_CR_LE_BAD_PSM:
623615f02b91SLuiz Augusto von Dentz 			l2cap_chan_del(chan, ECONNREFUSED);
623715f02b91SLuiz Augusto von Dentz 			break;
623815f02b91SLuiz Augusto von Dentz 
623915f02b91SLuiz Augusto von Dentz 		default:
624015f02b91SLuiz Augusto von Dentz 			/* If dcid was not set it means channels was refused */
624115f02b91SLuiz Augusto von Dentz 			if (!dcid) {
624215f02b91SLuiz Augusto von Dentz 				l2cap_chan_del(chan, ECONNREFUSED);
624315f02b91SLuiz Augusto von Dentz 				break;
624415f02b91SLuiz Augusto von Dentz 			}
624515f02b91SLuiz Augusto von Dentz 
624615f02b91SLuiz Augusto von Dentz 			chan->ident = 0;
624715f02b91SLuiz Augusto von Dentz 			chan->dcid = dcid;
624815f02b91SLuiz Augusto von Dentz 			chan->omtu = mtu;
624915f02b91SLuiz Augusto von Dentz 			chan->remote_mps = mps;
625015f02b91SLuiz Augusto von Dentz 			chan->tx_credits = credits;
625115f02b91SLuiz Augusto von Dentz 			l2cap_chan_ready(chan);
625215f02b91SLuiz Augusto von Dentz 			break;
625315f02b91SLuiz Augusto von Dentz 		}
625415f02b91SLuiz Augusto von Dentz 
625515f02b91SLuiz Augusto von Dentz 		l2cap_chan_unlock(chan);
625615f02b91SLuiz Augusto von Dentz 	}
625715f02b91SLuiz Augusto von Dentz 
625815f02b91SLuiz Augusto von Dentz 	mutex_unlock(&conn->chan_lock);
625915f02b91SLuiz Augusto von Dentz 
626015f02b91SLuiz Augusto von Dentz 	return err;
626115f02b91SLuiz Augusto von Dentz }
626215f02b91SLuiz Augusto von Dentz 
626315f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn,
626415f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
626515f02b91SLuiz Augusto von Dentz 					 u8 *data)
626615f02b91SLuiz Augusto von Dentz {
626715f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_req *req = (void *) data;
626815f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_reconf_rsp rsp;
626915f02b91SLuiz Augusto von Dentz 	u16 mtu, mps, result;
627015f02b91SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
627115f02b91SLuiz Augusto von Dentz 	int i, num_scid;
627215f02b91SLuiz Augusto von Dentz 
62734be5ca67SLuiz Augusto von Dentz 	if (!enable_ecred)
62744be5ca67SLuiz Augusto von Dentz 		return -EINVAL;
62754be5ca67SLuiz Augusto von Dentz 
627615f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
627715f02b91SLuiz Augusto von Dentz 		result = L2CAP_CR_LE_INVALID_PARAMS;
627815f02b91SLuiz Augusto von Dentz 		goto respond;
627915f02b91SLuiz Augusto von Dentz 	}
628015f02b91SLuiz Augusto von Dentz 
628115f02b91SLuiz Augusto von Dentz 	mtu = __le16_to_cpu(req->mtu);
628215f02b91SLuiz Augusto von Dentz 	mps = __le16_to_cpu(req->mps);
628315f02b91SLuiz Augusto von Dentz 
628415f02b91SLuiz Augusto von Dentz 	BT_DBG("mtu %u mps %u", mtu, mps);
628515f02b91SLuiz Augusto von Dentz 
628615f02b91SLuiz Augusto von Dentz 	if (mtu < L2CAP_ECRED_MIN_MTU) {
628715f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MTU;
628815f02b91SLuiz Augusto von Dentz 		goto respond;
628915f02b91SLuiz Augusto von Dentz 	}
629015f02b91SLuiz Augusto von Dentz 
629115f02b91SLuiz Augusto von Dentz 	if (mps < L2CAP_ECRED_MIN_MPS) {
629215f02b91SLuiz Augusto von Dentz 		result = L2CAP_RECONF_INVALID_MPS;
629315f02b91SLuiz Augusto von Dentz 		goto respond;
629415f02b91SLuiz Augusto von Dentz 	}
629515f02b91SLuiz Augusto von Dentz 
629615f02b91SLuiz Augusto von Dentz 	cmd_len -= sizeof(*req);
629715f02b91SLuiz Augusto von Dentz 	num_scid = cmd_len / sizeof(u16);
629815f02b91SLuiz Augusto von Dentz 	result = L2CAP_RECONF_SUCCESS;
629915f02b91SLuiz Augusto von Dentz 
630015f02b91SLuiz Augusto von Dentz 	for (i = 0; i < num_scid; i++) {
630115f02b91SLuiz Augusto von Dentz 		u16 scid;
630215f02b91SLuiz Augusto von Dentz 
630315f02b91SLuiz Augusto von Dentz 		scid = __le16_to_cpu(req->scid[i]);
630415f02b91SLuiz Augusto von Dentz 		if (!scid)
630515f02b91SLuiz Augusto von Dentz 			return -EPROTO;
630615f02b91SLuiz Augusto von Dentz 
630715f02b91SLuiz Augusto von Dentz 		chan = __l2cap_get_chan_by_dcid(conn, scid);
630815f02b91SLuiz Augusto von Dentz 		if (!chan)
630915f02b91SLuiz Augusto von Dentz 			continue;
631015f02b91SLuiz Augusto von Dentz 
631115f02b91SLuiz Augusto von Dentz 		/* If the MTU value is decreased for any of the included
631215f02b91SLuiz Augusto von Dentz 		 * channels, then the receiver shall disconnect all
631315f02b91SLuiz Augusto von Dentz 		 * included channels.
631415f02b91SLuiz Augusto von Dentz 		 */
631515f02b91SLuiz Augusto von Dentz 		if (chan->omtu > mtu) {
631615f02b91SLuiz Augusto von Dentz 			BT_ERR("chan %p decreased MTU %u -> %u", chan,
631715f02b91SLuiz Augusto von Dentz 			       chan->omtu, mtu);
631815f02b91SLuiz Augusto von Dentz 			result = L2CAP_RECONF_INVALID_MTU;
631915f02b91SLuiz Augusto von Dentz 		}
632015f02b91SLuiz Augusto von Dentz 
632115f02b91SLuiz Augusto von Dentz 		chan->omtu = mtu;
632215f02b91SLuiz Augusto von Dentz 		chan->remote_mps = mps;
632315f02b91SLuiz Augusto von Dentz 	}
632415f02b91SLuiz Augusto von Dentz 
632515f02b91SLuiz Augusto von Dentz respond:
632615f02b91SLuiz Augusto von Dentz 	rsp.result = cpu_to_le16(result);
632715f02b91SLuiz Augusto von Dentz 
632815f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, cmd->ident, L2CAP_ECRED_RECONF_RSP, sizeof(rsp),
632915f02b91SLuiz Augusto von Dentz 		       &rsp);
633015f02b91SLuiz Augusto von Dentz 
633115f02b91SLuiz Augusto von Dentz 	return 0;
633215f02b91SLuiz Augusto von Dentz }
633315f02b91SLuiz Augusto von Dentz 
633415f02b91SLuiz Augusto von Dentz static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
633515f02b91SLuiz Augusto von Dentz 					 struct l2cap_cmd_hdr *cmd, u16 cmd_len,
633615f02b91SLuiz Augusto von Dentz 					 u8 *data)
633715f02b91SLuiz Augusto von Dentz {
63381fa20d7dSLuiz Augusto von Dentz 	struct l2cap_chan *chan, *tmp;
633915f02b91SLuiz Augusto von Dentz 	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
634015f02b91SLuiz Augusto von Dentz 	u16 result;
634115f02b91SLuiz Augusto von Dentz 
634215f02b91SLuiz Augusto von Dentz 	if (cmd_len < sizeof(*rsp))
634315f02b91SLuiz Augusto von Dentz 		return -EPROTO;
634415f02b91SLuiz Augusto von Dentz 
634515f02b91SLuiz Augusto von Dentz 	result = __le16_to_cpu(rsp->result);
634615f02b91SLuiz Augusto von Dentz 
634715f02b91SLuiz Augusto von Dentz 	BT_DBG("result 0x%4.4x", rsp->result);
634815f02b91SLuiz Augusto von Dentz 
634915f02b91SLuiz Augusto von Dentz 	if (!result)
635015f02b91SLuiz Augusto von Dentz 		return 0;
635115f02b91SLuiz Augusto von Dentz 
63521fa20d7dSLuiz Augusto von Dentz 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
635315f02b91SLuiz Augusto von Dentz 		if (chan->ident != cmd->ident)
635415f02b91SLuiz Augusto von Dentz 			continue;
635515f02b91SLuiz Augusto von Dentz 
635615f02b91SLuiz Augusto von Dentz 		l2cap_chan_del(chan, ECONNRESET);
635715f02b91SLuiz Augusto von Dentz 	}
635815f02b91SLuiz Augusto von Dentz 
635915f02b91SLuiz Augusto von Dentz 	return 0;
636015f02b91SLuiz Augusto von Dentz }
636115f02b91SLuiz Augusto von Dentz 
636271fb4197SJohan Hedberg static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
636371fb4197SJohan Hedberg 				       struct l2cap_cmd_hdr *cmd, u16 cmd_len,
636471fb4197SJohan Hedberg 				       u8 *data)
636571fb4197SJohan Hedberg {
636671fb4197SJohan Hedberg 	struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
636771fb4197SJohan Hedberg 	struct l2cap_chan *chan;
636871fb4197SJohan Hedberg 
636971fb4197SJohan Hedberg 	if (cmd_len < sizeof(*rej))
637071fb4197SJohan Hedberg 		return -EPROTO;
637171fb4197SJohan Hedberg 
637271fb4197SJohan Hedberg 	mutex_lock(&conn->chan_lock);
637371fb4197SJohan Hedberg 
637471fb4197SJohan Hedberg 	chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
637571fb4197SJohan Hedberg 	if (!chan)
637671fb4197SJohan Hedberg 		goto done;
637771fb4197SJohan Hedberg 
637871fb4197SJohan Hedberg 	l2cap_chan_lock(chan);
637971fb4197SJohan Hedberg 	l2cap_chan_del(chan, ECONNREFUSED);
638071fb4197SJohan Hedberg 	l2cap_chan_unlock(chan);
638171fb4197SJohan Hedberg 
638271fb4197SJohan Hedberg done:
638371fb4197SJohan Hedberg 	mutex_unlock(&conn->chan_lock);
638471fb4197SJohan Hedberg 	return 0;
638571fb4197SJohan Hedberg }
638671fb4197SJohan Hedberg 
63873300d9a9SClaudio Takahasi static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
6388203e639eSJohan Hedberg 				   struct l2cap_cmd_hdr *cmd, u16 cmd_len,
6389203e639eSJohan Hedberg 				   u8 *data)
63903300d9a9SClaudio Takahasi {
6391b5ecba64SJohan Hedberg 	int err = 0;
6392b5ecba64SJohan Hedberg 
63933300d9a9SClaudio Takahasi 	switch (cmd->code) {
63943300d9a9SClaudio Takahasi 	case L2CAP_COMMAND_REJ:
639571fb4197SJohan Hedberg 		l2cap_le_command_rej(conn, cmd, cmd_len, data);
6396b5ecba64SJohan Hedberg 		break;
63973300d9a9SClaudio Takahasi 
63983300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_REQ:
6399b5ecba64SJohan Hedberg 		err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
6400b5ecba64SJohan Hedberg 		break;
64013300d9a9SClaudio Takahasi 
64023300d9a9SClaudio Takahasi 	case L2CAP_CONN_PARAM_UPDATE_RSP:
6403b5ecba64SJohan Hedberg 		break;
64043300d9a9SClaudio Takahasi 
6405f1496deeSJohan Hedberg 	case L2CAP_LE_CONN_RSP:
6406f1496deeSJohan Hedberg 		l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
6407b5ecba64SJohan Hedberg 		break;
6408f1496deeSJohan Hedberg 
640927e2d4c8SJohan Hedberg 	case L2CAP_LE_CONN_REQ:
6410b5ecba64SJohan Hedberg 		err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
6411b5ecba64SJohan Hedberg 		break;
641227e2d4c8SJohan Hedberg 
6413fad5fc89SJohan Hedberg 	case L2CAP_LE_CREDITS:
6414fad5fc89SJohan Hedberg 		err = l2cap_le_credits(conn, cmd, cmd_len, data);
6415fad5fc89SJohan Hedberg 		break;
6416fad5fc89SJohan Hedberg 
641715f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_REQ:
641815f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_req(conn, cmd, cmd_len, data);
641915f02b91SLuiz Augusto von Dentz 		break;
642015f02b91SLuiz Augusto von Dentz 
642115f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_CONN_RSP:
642215f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_conn_rsp(conn, cmd, cmd_len, data);
642315f02b91SLuiz Augusto von Dentz 		break;
642415f02b91SLuiz Augusto von Dentz 
642515f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_REQ:
642615f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_req(conn, cmd, cmd_len, data);
642715f02b91SLuiz Augusto von Dentz 		break;
642815f02b91SLuiz Augusto von Dentz 
642915f02b91SLuiz Augusto von Dentz 	case L2CAP_ECRED_RECONF_RSP:
643015f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_reconf_rsp(conn, cmd, cmd_len, data);
643115f02b91SLuiz Augusto von Dentz 		break;
643215f02b91SLuiz Augusto von Dentz 
64333defe01aSJohan Hedberg 	case L2CAP_DISCONN_REQ:
6434b5ecba64SJohan Hedberg 		err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
6435b5ecba64SJohan Hedberg 		break;
64363defe01aSJohan Hedberg 
64373defe01aSJohan Hedberg 	case L2CAP_DISCONN_RSP:
64383defe01aSJohan Hedberg 		l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
6439b5ecba64SJohan Hedberg 		break;
64403defe01aSJohan Hedberg 
64413300d9a9SClaudio Takahasi 	default:
64423300d9a9SClaudio Takahasi 		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
6443b5ecba64SJohan Hedberg 		err = -EINVAL;
6444b5ecba64SJohan Hedberg 		break;
64453300d9a9SClaudio Takahasi 	}
6446b5ecba64SJohan Hedberg 
6447b5ecba64SJohan Hedberg 	return err;
64483300d9a9SClaudio Takahasi }
64493300d9a9SClaudio Takahasi 
6450c5623556SJohan Hedberg static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
6451c5623556SJohan Hedberg 					struct sk_buff *skb)
6452c5623556SJohan Hedberg {
645369c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
64544f3e219dSMarcel Holtmann 	struct l2cap_cmd_hdr *cmd;
64554f3e219dSMarcel Holtmann 	u16 len;
6456c5623556SJohan Hedberg 	int err;
6457c5623556SJohan Hedberg 
645869c4e4e8SJohan Hedberg 	if (hcon->type != LE_LINK)
64593b166295SMarcel Holtmann 		goto drop;
646069c4e4e8SJohan Hedberg 
64614f3e219dSMarcel Holtmann 	if (skb->len < L2CAP_CMD_HDR_SIZE)
64624f3e219dSMarcel Holtmann 		goto drop;
6463c5623556SJohan Hedberg 
64644f3e219dSMarcel Holtmann 	cmd = (void *) skb->data;
64654f3e219dSMarcel Holtmann 	skb_pull(skb, L2CAP_CMD_HDR_SIZE);
6466c5623556SJohan Hedberg 
64674f3e219dSMarcel Holtmann 	len = le16_to_cpu(cmd->len);
6468c5623556SJohan Hedberg 
64694f3e219dSMarcel Holtmann 	BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len, cmd->ident);
64704f3e219dSMarcel Holtmann 
64714f3e219dSMarcel Holtmann 	if (len != skb->len || !cmd->ident) {
6472c5623556SJohan Hedberg 		BT_DBG("corrupted command");
64734f3e219dSMarcel Holtmann 		goto drop;
6474c5623556SJohan Hedberg 	}
6475c5623556SJohan Hedberg 
6476203e639eSJohan Hedberg 	err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
6477c5623556SJohan Hedberg 	if (err) {
6478c5623556SJohan Hedberg 		struct l2cap_cmd_rej_unk rej;
6479c5623556SJohan Hedberg 
6480c5623556SJohan Hedberg 		BT_ERR("Wrong link type (%d)", err);
6481c5623556SJohan Hedberg 
6482dcf4adbfSJoe Perches 		rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
64834f3e219dSMarcel Holtmann 		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
6484c5623556SJohan Hedberg 			       sizeof(rej), &rej);
6485c5623556SJohan Hedberg 	}
6486c5623556SJohan Hedberg 
64873b166295SMarcel Holtmann drop:
6488c5623556SJohan Hedberg 	kfree_skb(skb);
6489c5623556SJohan Hedberg }
6490c5623556SJohan Hedberg 
64913300d9a9SClaudio Takahasi static inline void l2cap_sig_channel(struct l2cap_conn *conn,
64923300d9a9SClaudio Takahasi 				     struct sk_buff *skb)
64930a708f8fSGustavo F. Padovan {
649469c4e4e8SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
649555cee73eSLuiz Augusto von Dentz 	struct l2cap_cmd_hdr *cmd;
64963300d9a9SClaudio Takahasi 	int err;
64970a708f8fSGustavo F. Padovan 
64980a708f8fSGustavo F. Padovan 	l2cap_raw_recv(conn, skb);
64990a708f8fSGustavo F. Padovan 
650069c4e4e8SJohan Hedberg 	if (hcon->type != ACL_LINK)
65013b166295SMarcel Holtmann 		goto drop;
650269c4e4e8SJohan Hedberg 
650355cee73eSLuiz Augusto von Dentz 	while (skb->len >= L2CAP_CMD_HDR_SIZE) {
650455cee73eSLuiz Augusto von Dentz 		u16 len;
65050a708f8fSGustavo F. Padovan 
650655cee73eSLuiz Augusto von Dentz 		cmd = (void *) skb->data;
650755cee73eSLuiz Augusto von Dentz 		skb_pull(skb, L2CAP_CMD_HDR_SIZE);
65080a708f8fSGustavo F. Padovan 
650955cee73eSLuiz Augusto von Dentz 		len = le16_to_cpu(cmd->len);
65100a708f8fSGustavo F. Padovan 
651155cee73eSLuiz Augusto von Dentz 		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd->code, len,
651255cee73eSLuiz Augusto von Dentz 		       cmd->ident);
651355cee73eSLuiz Augusto von Dentz 
651455cee73eSLuiz Augusto von Dentz 		if (len > skb->len || !cmd->ident) {
65150a708f8fSGustavo F. Padovan 			BT_DBG("corrupted command");
65160a708f8fSGustavo F. Padovan 			break;
65170a708f8fSGustavo F. Padovan 		}
65180a708f8fSGustavo F. Padovan 
651955cee73eSLuiz Augusto von Dentz 		err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data);
65200a708f8fSGustavo F. Padovan 		if (err) {
6521e2fd318eSIlia Kolomisnky 			struct l2cap_cmd_rej_unk rej;
65222c6d1a2eSGustavo F. Padovan 
65232c6d1a2eSGustavo F. Padovan 			BT_ERR("Wrong link type (%d)", err);
65240a708f8fSGustavo F. Padovan 
6525dcf4adbfSJoe Perches 			rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
652655cee73eSLuiz Augusto von Dentz 			l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
65272d792818SGustavo Padovan 				       sizeof(rej), &rej);
65280a708f8fSGustavo F. Padovan 		}
65290a708f8fSGustavo F. Padovan 
653055cee73eSLuiz Augusto von Dentz 		skb_pull(skb, len);
65310a708f8fSGustavo F. Padovan 	}
65320a708f8fSGustavo F. Padovan 
65333b166295SMarcel Holtmann drop:
65340a708f8fSGustavo F. Padovan 	kfree_skb(skb);
65350a708f8fSGustavo F. Padovan }
65360a708f8fSGustavo F. Padovan 
653747d1ec61SGustavo F. Padovan static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
65380a708f8fSGustavo F. Padovan {
65390a708f8fSGustavo F. Padovan 	u16 our_fcs, rcv_fcs;
6540e4ca6d98SAndrei Emeltchenko 	int hdr_size;
6541e4ca6d98SAndrei Emeltchenko 
6542e4ca6d98SAndrei Emeltchenko 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
6543e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_EXT_HDR_SIZE;
6544e4ca6d98SAndrei Emeltchenko 	else
6545e4ca6d98SAndrei Emeltchenko 		hdr_size = L2CAP_ENH_HDR_SIZE;
65460a708f8fSGustavo F. Padovan 
654747d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16) {
654803a51213SAndrei Emeltchenko 		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
65490a708f8fSGustavo F. Padovan 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
65500a708f8fSGustavo F. Padovan 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
65510a708f8fSGustavo F. Padovan 
65520a708f8fSGustavo F. Padovan 		if (our_fcs != rcv_fcs)
65530a708f8fSGustavo F. Padovan 			return -EBADMSG;
65540a708f8fSGustavo F. Padovan 	}
65550a708f8fSGustavo F. Padovan 	return 0;
65560a708f8fSGustavo F. Padovan }
65570a708f8fSGustavo F. Padovan 
65586ea00485SMat Martineau static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
65590a708f8fSGustavo F. Padovan {
6560e31f7633SMat Martineau 	struct l2cap_ctrl control;
65610a708f8fSGustavo F. Padovan 
6562e31f7633SMat Martineau 	BT_DBG("chan %p", chan);
65630a708f8fSGustavo F. Padovan 
6564e31f7633SMat Martineau 	memset(&control, 0, sizeof(control));
6565e31f7633SMat Martineau 	control.sframe = 1;
6566e31f7633SMat Martineau 	control.final = 1;
6567e31f7633SMat Martineau 	control.reqseq = chan->buffer_seq;
6568e31f7633SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
65690a708f8fSGustavo F. Padovan 
6570e2ab4353SGustavo F. Padovan 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6571e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RNR;
6572e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
65730a708f8fSGustavo F. Padovan 	}
65740a708f8fSGustavo F. Padovan 
6575e31f7633SMat Martineau 	if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
6576e31f7633SMat Martineau 	    chan->unacked_frames > 0)
6577e31f7633SMat Martineau 		__set_retrans_timer(chan);
65780a708f8fSGustavo F. Padovan 
6579e31f7633SMat Martineau 	/* Send pending iframes */
6580525cd185SGustavo F. Padovan 	l2cap_ertm_send(chan);
65810a708f8fSGustavo F. Padovan 
6582e2ab4353SGustavo F. Padovan 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
6583e31f7633SMat Martineau 	    test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
6584e31f7633SMat Martineau 		/* F-bit wasn't sent in an s-frame or i-frame yet, so
6585e31f7633SMat Martineau 		 * send it now.
6586e31f7633SMat Martineau 		 */
6587e31f7633SMat Martineau 		control.super = L2CAP_SUPER_RR;
6588e31f7633SMat Martineau 		l2cap_send_sframe(chan, &control);
65890a708f8fSGustavo F. Padovan 	}
65900a708f8fSGustavo F. Padovan }
65910a708f8fSGustavo F. Padovan 
65922d792818SGustavo Padovan static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag,
65932d792818SGustavo Padovan 			    struct sk_buff **last_frag)
65940a708f8fSGustavo F. Padovan {
659584084a31SMat Martineau 	/* skb->len reflects data in skb as well as all fragments
659684084a31SMat Martineau 	 * skb->data_len reflects only data in fragments
659784084a31SMat Martineau 	 */
659884084a31SMat Martineau 	if (!skb_has_frag_list(skb))
659984084a31SMat Martineau 		skb_shinfo(skb)->frag_list = new_frag;
660084084a31SMat Martineau 
660184084a31SMat Martineau 	new_frag->next = NULL;
660284084a31SMat Martineau 
660384084a31SMat Martineau 	(*last_frag)->next = new_frag;
660484084a31SMat Martineau 	*last_frag = new_frag;
660584084a31SMat Martineau 
660684084a31SMat Martineau 	skb->len += new_frag->len;
660784084a31SMat Martineau 	skb->data_len += new_frag->len;
660884084a31SMat Martineau 	skb->truesize += new_frag->truesize;
660984084a31SMat Martineau }
661084084a31SMat Martineau 
66114b51dae9SMat Martineau static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb,
66124b51dae9SMat Martineau 				struct l2cap_ctrl *control)
661384084a31SMat Martineau {
661484084a31SMat Martineau 	int err = -EINVAL;
66150a708f8fSGustavo F. Padovan 
66164b51dae9SMat Martineau 	switch (control->sar) {
66177e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_UNSEGMENTED:
661884084a31SMat Martineau 		if (chan->sdu)
661984084a31SMat Martineau 			break;
66200a708f8fSGustavo F. Padovan 
662180b98027SGustavo Padovan 		err = chan->ops->recv(chan, skb);
662284084a31SMat Martineau 		break;
66230a708f8fSGustavo F. Padovan 
66247e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_START:
662584084a31SMat Martineau 		if (chan->sdu)
662684084a31SMat Martineau 			break;
66270a708f8fSGustavo F. Padovan 
6628dbb50887SDaniel Borkmann 		if (!pskb_may_pull(skb, L2CAP_SDULEN_SIZE))
6629dbb50887SDaniel Borkmann 			break;
6630dbb50887SDaniel Borkmann 
66316f61fd47SGustavo F. Padovan 		chan->sdu_len = get_unaligned_le16(skb->data);
663203a51213SAndrei Emeltchenko 		skb_pull(skb, L2CAP_SDULEN_SIZE);
66330a708f8fSGustavo F. Padovan 
663484084a31SMat Martineau 		if (chan->sdu_len > chan->imtu) {
663584084a31SMat Martineau 			err = -EMSGSIZE;
663684084a31SMat Martineau 			break;
663784084a31SMat Martineau 		}
66380a708f8fSGustavo F. Padovan 
663984084a31SMat Martineau 		if (skb->len >= chan->sdu_len)
664084084a31SMat Martineau 			break;
664184084a31SMat Martineau 
664284084a31SMat Martineau 		chan->sdu = skb;
664384084a31SMat Martineau 		chan->sdu_last_frag = skb;
664484084a31SMat Martineau 
664584084a31SMat Martineau 		skb = NULL;
664684084a31SMat Martineau 		err = 0;
66470a708f8fSGustavo F. Padovan 		break;
66480a708f8fSGustavo F. Padovan 
66497e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_CONTINUE:
66506f61fd47SGustavo F. Padovan 		if (!chan->sdu)
665184084a31SMat Martineau 			break;
66520a708f8fSGustavo F. Padovan 
665384084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
665484084a31SMat Martineau 				&chan->sdu_last_frag);
665584084a31SMat Martineau 		skb = NULL;
66560a708f8fSGustavo F. Padovan 
665784084a31SMat Martineau 		if (chan->sdu->len >= chan->sdu_len)
665884084a31SMat Martineau 			break;
66590a708f8fSGustavo F. Padovan 
666084084a31SMat Martineau 		err = 0;
66610a708f8fSGustavo F. Padovan 		break;
66620a708f8fSGustavo F. Padovan 
66637e0ef6eeSAndrei Emeltchenko 	case L2CAP_SAR_END:
66646f61fd47SGustavo F. Padovan 		if (!chan->sdu)
666584084a31SMat Martineau 			break;
66660a708f8fSGustavo F. Padovan 
666784084a31SMat Martineau 		append_skb_frag(chan->sdu, skb,
666884084a31SMat Martineau 				&chan->sdu_last_frag);
666984084a31SMat Martineau 		skb = NULL;
66700a708f8fSGustavo F. Padovan 
667184084a31SMat Martineau 		if (chan->sdu->len != chan->sdu_len)
667284084a31SMat Martineau 			break;
66730a708f8fSGustavo F. Padovan 
667480b98027SGustavo Padovan 		err = chan->ops->recv(chan, chan->sdu);
66750a708f8fSGustavo F. Padovan 
667684084a31SMat Martineau 		if (!err) {
667784084a31SMat Martineau 			/* Reassembly complete */
667884084a31SMat Martineau 			chan->sdu = NULL;
667984084a31SMat Martineau 			chan->sdu_last_frag = NULL;
668084084a31SMat Martineau 			chan->sdu_len = 0;
66810a708f8fSGustavo F. Padovan 		}
66820a708f8fSGustavo F. Padovan 		break;
66830a708f8fSGustavo F. Padovan 	}
66840a708f8fSGustavo F. Padovan 
668584084a31SMat Martineau 	if (err) {
66860a708f8fSGustavo F. Padovan 		kfree_skb(skb);
66876f61fd47SGustavo F. Padovan 		kfree_skb(chan->sdu);
66886f61fd47SGustavo F. Padovan 		chan->sdu = NULL;
668984084a31SMat Martineau 		chan->sdu_last_frag = NULL;
669084084a31SMat Martineau 		chan->sdu_len = 0;
669184084a31SMat Martineau 	}
66920a708f8fSGustavo F. Padovan 
669384084a31SMat Martineau 	return err;
66940a708f8fSGustavo F. Padovan }
66950a708f8fSGustavo F. Padovan 
669632b32735SMat Martineau static int l2cap_resegment(struct l2cap_chan *chan)
669732b32735SMat Martineau {
669832b32735SMat Martineau 	/* Placeholder */
669932b32735SMat Martineau 	return 0;
670032b32735SMat Martineau }
670132b32735SMat Martineau 
6702e328140fSMat Martineau void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
67030a708f8fSGustavo F. Padovan {
670461aa4f5bSMat Martineau 	u8 event;
670561aa4f5bSMat Martineau 
670661aa4f5bSMat Martineau 	if (chan->mode != L2CAP_MODE_ERTM)
670761aa4f5bSMat Martineau 		return;
670861aa4f5bSMat Martineau 
670961aa4f5bSMat Martineau 	event = busy ? L2CAP_EV_LOCAL_BUSY_DETECTED : L2CAP_EV_LOCAL_BUSY_CLEAR;
6710401bb1f7SAndrei Emeltchenko 	l2cap_tx(chan, NULL, NULL, event);
67110a708f8fSGustavo F. Padovan }
67120a708f8fSGustavo F. Padovan 
6713d2a7ac5dSMat Martineau static int l2cap_rx_queued_iframes(struct l2cap_chan *chan)
6714d2a7ac5dSMat Martineau {
671563838725SMat Martineau 	int err = 0;
671663838725SMat Martineau 	/* Pass sequential frames to l2cap_reassemble_sdu()
671763838725SMat Martineau 	 * until a gap is encountered.
671863838725SMat Martineau 	 */
671963838725SMat Martineau 
672063838725SMat Martineau 	BT_DBG("chan %p", chan);
672163838725SMat Martineau 
672263838725SMat Martineau 	while (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
672363838725SMat Martineau 		struct sk_buff *skb;
672463838725SMat Martineau 		BT_DBG("Searching for skb with txseq %d (queue len %d)",
672563838725SMat Martineau 		       chan->buffer_seq, skb_queue_len(&chan->srej_q));
672663838725SMat Martineau 
672763838725SMat Martineau 		skb = l2cap_ertm_seq_in_queue(&chan->srej_q, chan->buffer_seq);
672863838725SMat Martineau 
672963838725SMat Martineau 		if (!skb)
673063838725SMat Martineau 			break;
673163838725SMat Martineau 
673263838725SMat Martineau 		skb_unlink(skb, &chan->srej_q);
673363838725SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
6734a4368ff3SJohan Hedberg 		err = l2cap_reassemble_sdu(chan, skb, &bt_cb(skb)->l2cap);
673563838725SMat Martineau 		if (err)
673663838725SMat Martineau 			break;
673763838725SMat Martineau 	}
673863838725SMat Martineau 
673963838725SMat Martineau 	if (skb_queue_empty(&chan->srej_q)) {
674063838725SMat Martineau 		chan->rx_state = L2CAP_RX_STATE_RECV;
674163838725SMat Martineau 		l2cap_send_ack(chan);
674263838725SMat Martineau 	}
674363838725SMat Martineau 
674463838725SMat Martineau 	return err;
6745d2a7ac5dSMat Martineau }
6746d2a7ac5dSMat Martineau 
6747d2a7ac5dSMat Martineau static void l2cap_handle_srej(struct l2cap_chan *chan,
6748d2a7ac5dSMat Martineau 			      struct l2cap_ctrl *control)
6749d2a7ac5dSMat Martineau {
6750f80842a8SMat Martineau 	struct sk_buff *skb;
6751f80842a8SMat Martineau 
6752f80842a8SMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6753f80842a8SMat Martineau 
6754f80842a8SMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6755f80842a8SMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
67565e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6757f80842a8SMat Martineau 		return;
6758f80842a8SMat Martineau 	}
6759f80842a8SMat Martineau 
6760f80842a8SMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6761f80842a8SMat Martineau 
6762f80842a8SMat Martineau 	if (skb == NULL) {
6763f80842a8SMat Martineau 		BT_DBG("Seq %d not available for retransmission",
6764f80842a8SMat Martineau 		       control->reqseq);
6765f80842a8SMat Martineau 		return;
6766f80842a8SMat Martineau 	}
6767f80842a8SMat Martineau 
6768a4368ff3SJohan Hedberg 	if (chan->max_tx != 0 && bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6769f80842a8SMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
67705e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6771f80842a8SMat Martineau 		return;
6772f80842a8SMat Martineau 	}
6773f80842a8SMat Martineau 
6774f80842a8SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6775f80842a8SMat Martineau 
6776f80842a8SMat Martineau 	if (control->poll) {
6777f80842a8SMat Martineau 		l2cap_pass_to_tx(chan, control);
6778f80842a8SMat Martineau 
6779f80842a8SMat Martineau 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
6780f80842a8SMat Martineau 		l2cap_retransmit(chan, control);
6781f80842a8SMat Martineau 		l2cap_ertm_send(chan);
6782f80842a8SMat Martineau 
6783f80842a8SMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6784f80842a8SMat Martineau 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
6785f80842a8SMat Martineau 			chan->srej_save_reqseq = control->reqseq;
6786f80842a8SMat Martineau 		}
6787f80842a8SMat Martineau 	} else {
6788f80842a8SMat Martineau 		l2cap_pass_to_tx_fbit(chan, control);
6789f80842a8SMat Martineau 
6790f80842a8SMat Martineau 		if (control->final) {
6791f80842a8SMat Martineau 			if (chan->srej_save_reqseq != control->reqseq ||
6792f80842a8SMat Martineau 			    !test_and_clear_bit(CONN_SREJ_ACT,
6793f80842a8SMat Martineau 						&chan->conn_state))
6794f80842a8SMat Martineau 				l2cap_retransmit(chan, control);
6795f80842a8SMat Martineau 		} else {
6796f80842a8SMat Martineau 			l2cap_retransmit(chan, control);
6797f80842a8SMat Martineau 			if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) {
6798f80842a8SMat Martineau 				set_bit(CONN_SREJ_ACT, &chan->conn_state);
6799f80842a8SMat Martineau 				chan->srej_save_reqseq = control->reqseq;
6800f80842a8SMat Martineau 			}
6801f80842a8SMat Martineau 		}
6802f80842a8SMat Martineau 	}
6803d2a7ac5dSMat Martineau }
6804d2a7ac5dSMat Martineau 
6805d2a7ac5dSMat Martineau static void l2cap_handle_rej(struct l2cap_chan *chan,
6806d2a7ac5dSMat Martineau 			     struct l2cap_ctrl *control)
6807d2a7ac5dSMat Martineau {
6808fcd289dfSMat Martineau 	struct sk_buff *skb;
6809fcd289dfSMat Martineau 
6810fcd289dfSMat Martineau 	BT_DBG("chan %p, control %p", chan, control);
6811fcd289dfSMat Martineau 
6812fcd289dfSMat Martineau 	if (control->reqseq == chan->next_tx_seq) {
6813fcd289dfSMat Martineau 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
68145e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6815fcd289dfSMat Martineau 		return;
6816fcd289dfSMat Martineau 	}
6817fcd289dfSMat Martineau 
6818fcd289dfSMat Martineau 	skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq);
6819fcd289dfSMat Martineau 
6820fcd289dfSMat Martineau 	if (chan->max_tx && skb &&
6821a4368ff3SJohan Hedberg 	    bt_cb(skb)->l2cap.retries >= chan->max_tx) {
6822fcd289dfSMat Martineau 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
68235e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
6824fcd289dfSMat Martineau 		return;
6825fcd289dfSMat Martineau 	}
6826fcd289dfSMat Martineau 
6827fcd289dfSMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
6828fcd289dfSMat Martineau 
6829fcd289dfSMat Martineau 	l2cap_pass_to_tx(chan, control);
6830fcd289dfSMat Martineau 
6831fcd289dfSMat Martineau 	if (control->final) {
6832fcd289dfSMat Martineau 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
6833fcd289dfSMat Martineau 			l2cap_retransmit_all(chan, control);
6834fcd289dfSMat Martineau 	} else {
6835fcd289dfSMat Martineau 		l2cap_retransmit_all(chan, control);
6836fcd289dfSMat Martineau 		l2cap_ertm_send(chan);
6837fcd289dfSMat Martineau 		if (chan->tx_state == L2CAP_TX_STATE_WAIT_F)
6838fcd289dfSMat Martineau 			set_bit(CONN_REJ_ACT, &chan->conn_state);
6839fcd289dfSMat Martineau 	}
6840d2a7ac5dSMat Martineau }
6841d2a7ac5dSMat Martineau 
68424b51dae9SMat Martineau static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq)
68434b51dae9SMat Martineau {
68444b51dae9SMat Martineau 	BT_DBG("chan %p, txseq %d", chan, txseq);
68454b51dae9SMat Martineau 
68464b51dae9SMat Martineau 	BT_DBG("last_acked_seq %d, expected_tx_seq %d", chan->last_acked_seq,
68474b51dae9SMat Martineau 	       chan->expected_tx_seq);
68484b51dae9SMat Martineau 
68494b51dae9SMat Martineau 	if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) {
68504b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
68514b51dae9SMat Martineau 		    chan->tx_win) {
68524b51dae9SMat Martineau 			/* See notes below regarding "double poll" and
68534b51dae9SMat Martineau 			 * invalid packets.
68544b51dae9SMat Martineau 			 */
68554b51dae9SMat Martineau 			if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
68564b51dae9SMat Martineau 				BT_DBG("Invalid/Ignore - after SREJ");
68574b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID_IGNORE;
68584b51dae9SMat Martineau 			} else {
68594b51dae9SMat Martineau 				BT_DBG("Invalid - in window after SREJ sent");
68604b51dae9SMat Martineau 				return L2CAP_TXSEQ_INVALID;
68614b51dae9SMat Martineau 			}
68624b51dae9SMat Martineau 		}
68634b51dae9SMat Martineau 
68644b51dae9SMat Martineau 		if (chan->srej_list.head == txseq) {
68654b51dae9SMat Martineau 			BT_DBG("Expected SREJ");
68664b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED_SREJ;
68674b51dae9SMat Martineau 		}
68684b51dae9SMat Martineau 
68694b51dae9SMat Martineau 		if (l2cap_ertm_seq_in_queue(&chan->srej_q, txseq)) {
68704b51dae9SMat Martineau 			BT_DBG("Duplicate SREJ - txseq already stored");
68714b51dae9SMat Martineau 			return L2CAP_TXSEQ_DUPLICATE_SREJ;
68724b51dae9SMat Martineau 		}
68734b51dae9SMat Martineau 
68744b51dae9SMat Martineau 		if (l2cap_seq_list_contains(&chan->srej_list, txseq)) {
68754b51dae9SMat Martineau 			BT_DBG("Unexpected SREJ - not requested");
68764b51dae9SMat Martineau 			return L2CAP_TXSEQ_UNEXPECTED_SREJ;
68774b51dae9SMat Martineau 		}
68784b51dae9SMat Martineau 	}
68794b51dae9SMat Martineau 
68804b51dae9SMat Martineau 	if (chan->expected_tx_seq == txseq) {
68814b51dae9SMat Martineau 		if (__seq_offset(chan, txseq, chan->last_acked_seq) >=
68824b51dae9SMat Martineau 		    chan->tx_win) {
68834b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
68844b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
68854b51dae9SMat Martineau 		} else {
68864b51dae9SMat Martineau 			BT_DBG("Expected");
68874b51dae9SMat Martineau 			return L2CAP_TXSEQ_EXPECTED;
68884b51dae9SMat Martineau 		}
68894b51dae9SMat Martineau 	}
68904b51dae9SMat Martineau 
68914b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) <
68922d792818SGustavo Padovan 	    __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) {
68934b51dae9SMat Martineau 		BT_DBG("Duplicate - expected_tx_seq later than txseq");
68944b51dae9SMat Martineau 		return L2CAP_TXSEQ_DUPLICATE;
68954b51dae9SMat Martineau 	}
68964b51dae9SMat Martineau 
68974b51dae9SMat Martineau 	if (__seq_offset(chan, txseq, chan->last_acked_seq) >= chan->tx_win) {
68984b51dae9SMat Martineau 		/* A source of invalid packets is a "double poll" condition,
68994b51dae9SMat Martineau 		 * where delays cause us to send multiple poll packets.  If
69004b51dae9SMat Martineau 		 * the remote stack receives and processes both polls,
69014b51dae9SMat Martineau 		 * sequence numbers can wrap around in such a way that a
69024b51dae9SMat Martineau 		 * resent frame has a sequence number that looks like new data
69034b51dae9SMat Martineau 		 * with a sequence gap.  This would trigger an erroneous SREJ
69044b51dae9SMat Martineau 		 * request.
69054b51dae9SMat Martineau 		 *
69064b51dae9SMat Martineau 		 * Fortunately, this is impossible with a tx window that's
69074b51dae9SMat Martineau 		 * less than half of the maximum sequence number, which allows
69084b51dae9SMat Martineau 		 * invalid frames to be safely ignored.
69094b51dae9SMat Martineau 		 *
69104b51dae9SMat Martineau 		 * With tx window sizes greater than half of the tx window
69114b51dae9SMat Martineau 		 * maximum, the frame is invalid and cannot be ignored.  This
69124b51dae9SMat Martineau 		 * causes a disconnect.
69134b51dae9SMat Martineau 		 */
69144b51dae9SMat Martineau 
69154b51dae9SMat Martineau 		if (chan->tx_win <= ((chan->tx_win_max + 1) >> 1)) {
69164b51dae9SMat Martineau 			BT_DBG("Invalid/Ignore - txseq outside tx window");
69174b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID_IGNORE;
69184b51dae9SMat Martineau 		} else {
69194b51dae9SMat Martineau 			BT_DBG("Invalid - txseq outside tx window");
69204b51dae9SMat Martineau 			return L2CAP_TXSEQ_INVALID;
69214b51dae9SMat Martineau 		}
69224b51dae9SMat Martineau 	} else {
69234b51dae9SMat Martineau 		BT_DBG("Unexpected - txseq indicates missing frames");
69244b51dae9SMat Martineau 		return L2CAP_TXSEQ_UNEXPECTED;
69254b51dae9SMat Martineau 	}
69264b51dae9SMat Martineau }
69274b51dae9SMat Martineau 
6928d2a7ac5dSMat Martineau static int l2cap_rx_state_recv(struct l2cap_chan *chan,
6929d2a7ac5dSMat Martineau 			       struct l2cap_ctrl *control,
6930d2a7ac5dSMat Martineau 			       struct sk_buff *skb, u8 event)
6931d2a7ac5dSMat Martineau {
69323aff8aacSMaxim Mikityanskiy 	struct l2cap_ctrl local_control;
6933d2a7ac5dSMat Martineau 	int err = 0;
6934941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
6935d2a7ac5dSMat Martineau 
6936d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
6937d2a7ac5dSMat Martineau 	       event);
6938d2a7ac5dSMat Martineau 
6939d2a7ac5dSMat Martineau 	switch (event) {
6940d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
6941d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, control->txseq)) {
6942d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
6943d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6944d2a7ac5dSMat Martineau 
6945d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6946d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding expected seq %d",
6947d2a7ac5dSMat Martineau 				       control->txseq);
6948d2a7ac5dSMat Martineau 				break;
6949d2a7ac5dSMat Martineau 			}
6950d2a7ac5dSMat Martineau 
6951d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan,
6952d2a7ac5dSMat Martineau 							   control->txseq);
6953d2a7ac5dSMat Martineau 
6954d2a7ac5dSMat Martineau 			chan->buffer_seq = chan->expected_tx_seq;
6955941247f9SPeter Senna Tschudin 			skb_in_use = true;
6956d2a7ac5dSMat Martineau 
69573aff8aacSMaxim Mikityanskiy 			/* l2cap_reassemble_sdu may free skb, hence invalidate
69583aff8aacSMaxim Mikityanskiy 			 * control, so make a copy in advance to use it after
69593aff8aacSMaxim Mikityanskiy 			 * l2cap_reassemble_sdu returns and to avoid the race
69603aff8aacSMaxim Mikityanskiy 			 * condition, for example:
69613aff8aacSMaxim Mikityanskiy 			 *
69623aff8aacSMaxim Mikityanskiy 			 * The current thread calls:
69633aff8aacSMaxim Mikityanskiy 			 *   l2cap_reassemble_sdu
69643aff8aacSMaxim Mikityanskiy 			 *     chan->ops->recv == l2cap_sock_recv_cb
69653aff8aacSMaxim Mikityanskiy 			 *       __sock_queue_rcv_skb
69663aff8aacSMaxim Mikityanskiy 			 * Another thread calls:
69673aff8aacSMaxim Mikityanskiy 			 *   bt_sock_recvmsg
69683aff8aacSMaxim Mikityanskiy 			 *     skb_recv_datagram
69693aff8aacSMaxim Mikityanskiy 			 *     skb_free_datagram
69703aff8aacSMaxim Mikityanskiy 			 * Then the current thread tries to access control, but
69713aff8aacSMaxim Mikityanskiy 			 * it was freed by skb_free_datagram.
69723aff8aacSMaxim Mikityanskiy 			 */
69733aff8aacSMaxim Mikityanskiy 			local_control = *control;
6974d2a7ac5dSMat Martineau 			err = l2cap_reassemble_sdu(chan, skb, control);
6975d2a7ac5dSMat Martineau 			if (err)
6976d2a7ac5dSMat Martineau 				break;
6977d2a7ac5dSMat Martineau 
69783aff8aacSMaxim Mikityanskiy 			if (local_control.final) {
6979d2a7ac5dSMat Martineau 				if (!test_and_clear_bit(CONN_REJ_ACT,
6980d2a7ac5dSMat Martineau 							&chan->conn_state)) {
69813aff8aacSMaxim Mikityanskiy 					local_control.final = 0;
69823aff8aacSMaxim Mikityanskiy 					l2cap_retransmit_all(chan, &local_control);
6983d2a7ac5dSMat Martineau 					l2cap_ertm_send(chan);
6984d2a7ac5dSMat Martineau 				}
6985d2a7ac5dSMat Martineau 			}
6986d2a7ac5dSMat Martineau 
6987d2a7ac5dSMat Martineau 			if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
6988d2a7ac5dSMat Martineau 				l2cap_send_ack(chan);
6989d2a7ac5dSMat Martineau 			break;
6990d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
6991d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
6992d2a7ac5dSMat Martineau 
6993d2a7ac5dSMat Martineau 			/* Can't issue SREJ frames in the local busy state.
6994d2a7ac5dSMat Martineau 			 * Drop this frame, it will be seen as missing
6995d2a7ac5dSMat Martineau 			 * when local busy is exited.
6996d2a7ac5dSMat Martineau 			 */
6997d2a7ac5dSMat Martineau 			if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
6998d2a7ac5dSMat Martineau 				BT_DBG("Busy, discarding unexpected seq %d",
6999d2a7ac5dSMat Martineau 				       control->txseq);
7000d2a7ac5dSMat Martineau 				break;
7001d2a7ac5dSMat Martineau 			}
7002d2a7ac5dSMat Martineau 
7003d2a7ac5dSMat Martineau 			/* There was a gap in the sequence, so an SREJ
7004d2a7ac5dSMat Martineau 			 * must be sent for each missing frame.  The
7005d2a7ac5dSMat Martineau 			 * current frame is stored for later use.
7006d2a7ac5dSMat Martineau 			 */
7007d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7008941247f9SPeter Senna Tschudin 			skb_in_use = true;
7009d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7010d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7011d2a7ac5dSMat Martineau 
7012d2a7ac5dSMat Martineau 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
7013d2a7ac5dSMat Martineau 			l2cap_seq_list_clear(&chan->srej_list);
7014d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
7015d2a7ac5dSMat Martineau 
7016d2a7ac5dSMat Martineau 			chan->rx_state = L2CAP_RX_STATE_SREJ_SENT;
7017d2a7ac5dSMat Martineau 			break;
7018d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
7019d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7020d2a7ac5dSMat Martineau 			break;
7021d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
7022d2a7ac5dSMat Martineau 			break;
7023d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
7024d2a7ac5dSMat Martineau 		default:
70255e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7026d2a7ac5dSMat Martineau 			break;
7027d2a7ac5dSMat Martineau 		}
7028d2a7ac5dSMat Martineau 		break;
7029d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
7030d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7031d2a7ac5dSMat Martineau 		if (control->final) {
7032d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7033d2a7ac5dSMat Martineau 
7034e6a3ee6eSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
7035e6a3ee6eSMat Martineau 			    !__chan_is_moving(chan)) {
7036d2a7ac5dSMat Martineau 				control->final = 0;
7037d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
7038d2a7ac5dSMat Martineau 			}
7039d2a7ac5dSMat Martineau 
7040d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
7041d2a7ac5dSMat Martineau 		} else if (control->poll) {
7042d2a7ac5dSMat Martineau 			l2cap_send_i_or_rr_or_rnr(chan);
7043d2a7ac5dSMat Martineau 		} else {
7044d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7045d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7046d2a7ac5dSMat Martineau 			    chan->unacked_frames)
7047d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7048d2a7ac5dSMat Martineau 
7049d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
7050d2a7ac5dSMat Martineau 		}
7051d2a7ac5dSMat Martineau 		break;
7052d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
7053d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7054d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7055d2a7ac5dSMat Martineau 		if (control && control->poll) {
7056d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
7057d2a7ac5dSMat Martineau 			l2cap_send_rr_or_rnr(chan, 0);
7058d2a7ac5dSMat Martineau 		}
7059d2a7ac5dSMat Martineau 		__clear_retrans_timer(chan);
7060d2a7ac5dSMat Martineau 		l2cap_seq_list_clear(&chan->retrans_list);
7061d2a7ac5dSMat Martineau 		break;
7062d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
7063d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
7064d2a7ac5dSMat Martineau 		break;
7065d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
7066d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
7067d2a7ac5dSMat Martineau 		break;
7068d2a7ac5dSMat Martineau 	default:
7069d2a7ac5dSMat Martineau 		break;
7070d2a7ac5dSMat Martineau 	}
7071d2a7ac5dSMat Martineau 
7072d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
7073d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
7074d2a7ac5dSMat Martineau 		kfree_skb(skb);
7075d2a7ac5dSMat Martineau 	}
7076d2a7ac5dSMat Martineau 
7077d2a7ac5dSMat Martineau 	return err;
7078d2a7ac5dSMat Martineau }
7079d2a7ac5dSMat Martineau 
7080d2a7ac5dSMat Martineau static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
7081d2a7ac5dSMat Martineau 				    struct l2cap_ctrl *control,
7082d2a7ac5dSMat Martineau 				    struct sk_buff *skb, u8 event)
7083d2a7ac5dSMat Martineau {
7084d2a7ac5dSMat Martineau 	int err = 0;
7085d2a7ac5dSMat Martineau 	u16 txseq = control->txseq;
7086941247f9SPeter Senna Tschudin 	bool skb_in_use = false;
7087d2a7ac5dSMat Martineau 
7088d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
7089d2a7ac5dSMat Martineau 	       event);
7090d2a7ac5dSMat Martineau 
7091d2a7ac5dSMat Martineau 	switch (event) {
7092d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_IFRAME:
7093d2a7ac5dSMat Martineau 		switch (l2cap_classify_txseq(chan, txseq)) {
7094d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED:
7095d2a7ac5dSMat Martineau 			/* Keep frame for reassembly later */
7096d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7097d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7098941247f9SPeter Senna Tschudin 			skb_in_use = true;
7099d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7100d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7101d2a7ac5dSMat Martineau 
7102d2a7ac5dSMat Martineau 			chan->expected_tx_seq = __next_seq(chan, txseq);
7103d2a7ac5dSMat Martineau 			break;
7104d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_EXPECTED_SREJ:
7105d2a7ac5dSMat Martineau 			l2cap_seq_list_pop(&chan->srej_list);
7106d2a7ac5dSMat Martineau 
7107d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7108d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7109941247f9SPeter Senna Tschudin 			skb_in_use = true;
7110d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7111d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7112d2a7ac5dSMat Martineau 
7113d2a7ac5dSMat Martineau 			err = l2cap_rx_queued_iframes(chan);
7114d2a7ac5dSMat Martineau 			if (err)
7115d2a7ac5dSMat Martineau 				break;
7116d2a7ac5dSMat Martineau 
7117d2a7ac5dSMat Martineau 			break;
7118d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED:
7119d2a7ac5dSMat Martineau 			/* Got a frame that can't be reassembled yet.
7120d2a7ac5dSMat Martineau 			 * Save it for later, and send SREJs to cover
7121d2a7ac5dSMat Martineau 			 * the missing frames.
7122d2a7ac5dSMat Martineau 			 */
7123d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7124941247f9SPeter Senna Tschudin 			skb_in_use = true;
7125d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7126d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7127d2a7ac5dSMat Martineau 
7128d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7129d2a7ac5dSMat Martineau 			l2cap_send_srej(chan, control->txseq);
7130d2a7ac5dSMat Martineau 			break;
7131d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_UNEXPECTED_SREJ:
7132d2a7ac5dSMat Martineau 			/* This frame was requested with an SREJ, but
7133d2a7ac5dSMat Martineau 			 * some expected retransmitted frames are
7134d2a7ac5dSMat Martineau 			 * missing.  Request retransmission of missing
7135d2a7ac5dSMat Martineau 			 * SREJ'd frames.
7136d2a7ac5dSMat Martineau 			 */
7137d2a7ac5dSMat Martineau 			skb_queue_tail(&chan->srej_q, skb);
7138941247f9SPeter Senna Tschudin 			skb_in_use = true;
7139d2a7ac5dSMat Martineau 			BT_DBG("Queued %p (queue len %d)", skb,
7140d2a7ac5dSMat Martineau 			       skb_queue_len(&chan->srej_q));
7141d2a7ac5dSMat Martineau 
7142d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7143d2a7ac5dSMat Martineau 			l2cap_send_srej_list(chan, control->txseq);
7144d2a7ac5dSMat Martineau 			break;
7145d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE_SREJ:
7146d2a7ac5dSMat Martineau 			/* We've already queued this frame.  Drop this copy. */
7147d2a7ac5dSMat Martineau 			l2cap_pass_to_tx(chan, control);
7148d2a7ac5dSMat Martineau 			break;
7149d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_DUPLICATE:
7150d2a7ac5dSMat Martineau 			/* Expecting a later sequence number, so this frame
7151d2a7ac5dSMat Martineau 			 * was already received.  Ignore it completely.
7152d2a7ac5dSMat Martineau 			 */
7153d2a7ac5dSMat Martineau 			break;
7154d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID_IGNORE:
7155d2a7ac5dSMat Martineau 			break;
7156d2a7ac5dSMat Martineau 		case L2CAP_TXSEQ_INVALID:
7157d2a7ac5dSMat Martineau 		default:
71585e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7159d2a7ac5dSMat Martineau 			break;
7160d2a7ac5dSMat Martineau 		}
7161d2a7ac5dSMat Martineau 		break;
7162d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RR:
7163d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7164d2a7ac5dSMat Martineau 		if (control->final) {
7165d2a7ac5dSMat Martineau 			clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7166d2a7ac5dSMat Martineau 
7167d2a7ac5dSMat Martineau 			if (!test_and_clear_bit(CONN_REJ_ACT,
7168d2a7ac5dSMat Martineau 						&chan->conn_state)) {
7169d2a7ac5dSMat Martineau 				control->final = 0;
7170d2a7ac5dSMat Martineau 				l2cap_retransmit_all(chan, control);
7171d2a7ac5dSMat Martineau 			}
7172d2a7ac5dSMat Martineau 
7173d2a7ac5dSMat Martineau 			l2cap_ertm_send(chan);
7174d2a7ac5dSMat Martineau 		} else if (control->poll) {
7175d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7176d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7177d2a7ac5dSMat Martineau 			    chan->unacked_frames) {
7178d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7179d2a7ac5dSMat Martineau 			}
7180d2a7ac5dSMat Martineau 
7181d2a7ac5dSMat Martineau 			set_bit(CONN_SEND_FBIT, &chan->conn_state);
7182d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7183d2a7ac5dSMat Martineau 		} else {
7184d2a7ac5dSMat Martineau 			if (test_and_clear_bit(CONN_REMOTE_BUSY,
7185d2a7ac5dSMat Martineau 					       &chan->conn_state) &&
7186d2a7ac5dSMat Martineau 			    chan->unacked_frames)
7187d2a7ac5dSMat Martineau 				__set_retrans_timer(chan);
7188d2a7ac5dSMat Martineau 
7189d2a7ac5dSMat Martineau 			l2cap_send_ack(chan);
7190d2a7ac5dSMat Martineau 		}
7191d2a7ac5dSMat Martineau 		break;
7192d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_RNR:
7193d2a7ac5dSMat Martineau 		set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
7194d2a7ac5dSMat Martineau 		l2cap_pass_to_tx(chan, control);
7195d2a7ac5dSMat Martineau 		if (control->poll) {
7196d2a7ac5dSMat Martineau 			l2cap_send_srej_tail(chan);
7197d2a7ac5dSMat Martineau 		} else {
7198d2a7ac5dSMat Martineau 			struct l2cap_ctrl rr_control;
7199d2a7ac5dSMat Martineau 			memset(&rr_control, 0, sizeof(rr_control));
7200d2a7ac5dSMat Martineau 			rr_control.sframe = 1;
7201d2a7ac5dSMat Martineau 			rr_control.super = L2CAP_SUPER_RR;
7202d2a7ac5dSMat Martineau 			rr_control.reqseq = chan->buffer_seq;
7203d2a7ac5dSMat Martineau 			l2cap_send_sframe(chan, &rr_control);
7204d2a7ac5dSMat Martineau 		}
7205d2a7ac5dSMat Martineau 
7206d2a7ac5dSMat Martineau 		break;
7207d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_REJ:
7208d2a7ac5dSMat Martineau 		l2cap_handle_rej(chan, control);
7209d2a7ac5dSMat Martineau 		break;
7210d2a7ac5dSMat Martineau 	case L2CAP_EV_RECV_SREJ:
7211d2a7ac5dSMat Martineau 		l2cap_handle_srej(chan, control);
7212d2a7ac5dSMat Martineau 		break;
7213d2a7ac5dSMat Martineau 	}
7214d2a7ac5dSMat Martineau 
7215d2a7ac5dSMat Martineau 	if (skb && !skb_in_use) {
7216d2a7ac5dSMat Martineau 		BT_DBG("Freeing %p", skb);
7217d2a7ac5dSMat Martineau 		kfree_skb(skb);
7218d2a7ac5dSMat Martineau 	}
7219d2a7ac5dSMat Martineau 
7220d2a7ac5dSMat Martineau 	return err;
7221d2a7ac5dSMat Martineau }
7222d2a7ac5dSMat Martineau 
722332b32735SMat Martineau static int l2cap_finish_move(struct l2cap_chan *chan)
722432b32735SMat Martineau {
722532b32735SMat Martineau 	BT_DBG("chan %p", chan);
722632b32735SMat Martineau 
722732b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
722832b32735SMat Martineau 
722932b32735SMat Martineau 	if (chan->hs_hcon)
723032b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
723132b32735SMat Martineau 	else
723232b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
723332b32735SMat Martineau 
723432b32735SMat Martineau 	return l2cap_resegment(chan);
723532b32735SMat Martineau }
723632b32735SMat Martineau 
723732b32735SMat Martineau static int l2cap_rx_state_wait_p(struct l2cap_chan *chan,
723832b32735SMat Martineau 				 struct l2cap_ctrl *control,
723932b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
724032b32735SMat Martineau {
724132b32735SMat Martineau 	int err;
724232b32735SMat Martineau 
724332b32735SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
724432b32735SMat Martineau 	       event);
724532b32735SMat Martineau 
724632b32735SMat Martineau 	if (!control->poll)
724732b32735SMat Martineau 		return -EPROTO;
724832b32735SMat Martineau 
724932b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
725032b32735SMat Martineau 
725132b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
725232b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
725332b32735SMat Martineau 	else
725432b32735SMat Martineau 		chan->tx_send_head = NULL;
725532b32735SMat Martineau 
725632b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
725732b32735SMat Martineau 	 * by the receiver.
725832b32735SMat Martineau 	 */
725932b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
726032b32735SMat Martineau 	chan->unacked_frames = 0;
726132b32735SMat Martineau 
726232b32735SMat Martineau 	err = l2cap_finish_move(chan);
726332b32735SMat Martineau 	if (err)
726432b32735SMat Martineau 		return err;
726532b32735SMat Martineau 
726632b32735SMat Martineau 	set_bit(CONN_SEND_FBIT, &chan->conn_state);
726732b32735SMat Martineau 	l2cap_send_i_or_rr_or_rnr(chan);
726832b32735SMat Martineau 
726932b32735SMat Martineau 	if (event == L2CAP_EV_RECV_IFRAME)
727032b32735SMat Martineau 		return -EPROTO;
727132b32735SMat Martineau 
727232b32735SMat Martineau 	return l2cap_rx_state_recv(chan, control, NULL, event);
727332b32735SMat Martineau }
727432b32735SMat Martineau 
727532b32735SMat Martineau static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
727632b32735SMat Martineau 				 struct l2cap_ctrl *control,
727732b32735SMat Martineau 				 struct sk_buff *skb, u8 event)
727832b32735SMat Martineau {
727932b32735SMat Martineau 	int err;
728032b32735SMat Martineau 
728132b32735SMat Martineau 	if (!control->final)
728232b32735SMat Martineau 		return -EPROTO;
728332b32735SMat Martineau 
728432b32735SMat Martineau 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
728532b32735SMat Martineau 
728632b32735SMat Martineau 	chan->rx_state = L2CAP_RX_STATE_RECV;
728732b32735SMat Martineau 	l2cap_process_reqseq(chan, control->reqseq);
728832b32735SMat Martineau 
728932b32735SMat Martineau 	if (!skb_queue_empty(&chan->tx_q))
729032b32735SMat Martineau 		chan->tx_send_head = skb_peek(&chan->tx_q);
729132b32735SMat Martineau 	else
729232b32735SMat Martineau 		chan->tx_send_head = NULL;
729332b32735SMat Martineau 
729432b32735SMat Martineau 	/* Rewind next_tx_seq to the point expected
729532b32735SMat Martineau 	 * by the receiver.
729632b32735SMat Martineau 	 */
729732b32735SMat Martineau 	chan->next_tx_seq = control->reqseq;
729832b32735SMat Martineau 	chan->unacked_frames = 0;
729932b32735SMat Martineau 
730032b32735SMat Martineau 	if (chan->hs_hcon)
730132b32735SMat Martineau 		chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
730232b32735SMat Martineau 	else
730332b32735SMat Martineau 		chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
730432b32735SMat Martineau 
730532b32735SMat Martineau 	err = l2cap_resegment(chan);
730632b32735SMat Martineau 
730732b32735SMat Martineau 	if (!err)
730832b32735SMat Martineau 		err = l2cap_rx_state_recv(chan, control, skb, event);
730932b32735SMat Martineau 
731032b32735SMat Martineau 	return err;
731132b32735SMat Martineau }
731232b32735SMat Martineau 
7313d2a7ac5dSMat Martineau static bool __valid_reqseq(struct l2cap_chan *chan, u16 reqseq)
7314d2a7ac5dSMat Martineau {
7315d2a7ac5dSMat Martineau 	/* Make sure reqseq is for a packet that has been sent but not acked */
7316d2a7ac5dSMat Martineau 	u16 unacked;
7317d2a7ac5dSMat Martineau 
7318d2a7ac5dSMat Martineau 	unacked = __seq_offset(chan, chan->next_tx_seq, chan->expected_ack_seq);
7319d2a7ac5dSMat Martineau 	return __seq_offset(chan, chan->next_tx_seq, reqseq) <= unacked;
7320d2a7ac5dSMat Martineau }
7321d2a7ac5dSMat Martineau 
7322cec8ab6eSMat Martineau static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7323cec8ab6eSMat Martineau 		    struct sk_buff *skb, u8 event)
73240a708f8fSGustavo F. Padovan {
7325d2a7ac5dSMat Martineau 	int err = 0;
7326d2a7ac5dSMat Martineau 
7327d2a7ac5dSMat Martineau 	BT_DBG("chan %p, control %p, skb %p, event %d, state %d", chan,
7328d2a7ac5dSMat Martineau 	       control, skb, event, chan->rx_state);
7329d2a7ac5dSMat Martineau 
7330d2a7ac5dSMat Martineau 	if (__valid_reqseq(chan, control->reqseq)) {
7331d2a7ac5dSMat Martineau 		switch (chan->rx_state) {
7332d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_RECV:
7333d2a7ac5dSMat Martineau 			err = l2cap_rx_state_recv(chan, control, skb, event);
7334d2a7ac5dSMat Martineau 			break;
7335d2a7ac5dSMat Martineau 		case L2CAP_RX_STATE_SREJ_SENT:
7336d2a7ac5dSMat Martineau 			err = l2cap_rx_state_srej_sent(chan, control, skb,
7337d2a7ac5dSMat Martineau 						       event);
7338d2a7ac5dSMat Martineau 			break;
733932b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_P:
734032b32735SMat Martineau 			err = l2cap_rx_state_wait_p(chan, control, skb, event);
734132b32735SMat Martineau 			break;
734232b32735SMat Martineau 		case L2CAP_RX_STATE_WAIT_F:
734332b32735SMat Martineau 			err = l2cap_rx_state_wait_f(chan, control, skb, event);
734432b32735SMat Martineau 			break;
7345d2a7ac5dSMat Martineau 		default:
7346d2a7ac5dSMat Martineau 			/* shut it down */
7347d2a7ac5dSMat Martineau 			break;
7348d2a7ac5dSMat Martineau 		}
7349d2a7ac5dSMat Martineau 	} else {
7350d2a7ac5dSMat Martineau 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
7351d2a7ac5dSMat Martineau 		       control->reqseq, chan->next_tx_seq,
7352d2a7ac5dSMat Martineau 		       chan->expected_ack_seq);
73535e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
7354d2a7ac5dSMat Martineau 	}
7355d2a7ac5dSMat Martineau 
7356d2a7ac5dSMat Martineau 	return err;
7357cec8ab6eSMat Martineau }
7358cec8ab6eSMat Martineau 
7359cec8ab6eSMat Martineau static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
7360cec8ab6eSMat Martineau 			   struct sk_buff *skb)
7361cec8ab6eSMat Martineau {
73623aff8aacSMaxim Mikityanskiy 	/* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
73633aff8aacSMaxim Mikityanskiy 	 * the txseq field in advance to use it after l2cap_reassemble_sdu
73643aff8aacSMaxim Mikityanskiy 	 * returns and to avoid the race condition, for example:
73653aff8aacSMaxim Mikityanskiy 	 *
73663aff8aacSMaxim Mikityanskiy 	 * The current thread calls:
73673aff8aacSMaxim Mikityanskiy 	 *   l2cap_reassemble_sdu
73683aff8aacSMaxim Mikityanskiy 	 *     chan->ops->recv == l2cap_sock_recv_cb
73693aff8aacSMaxim Mikityanskiy 	 *       __sock_queue_rcv_skb
73703aff8aacSMaxim Mikityanskiy 	 * Another thread calls:
73713aff8aacSMaxim Mikityanskiy 	 *   bt_sock_recvmsg
73723aff8aacSMaxim Mikityanskiy 	 *     skb_recv_datagram
73733aff8aacSMaxim Mikityanskiy 	 *     skb_free_datagram
73743aff8aacSMaxim Mikityanskiy 	 * Then the current thread tries to access control, but it was freed by
73753aff8aacSMaxim Mikityanskiy 	 * skb_free_datagram.
73763aff8aacSMaxim Mikityanskiy 	 */
73773aff8aacSMaxim Mikityanskiy 	u16 txseq = control->txseq;
73783aff8aacSMaxim Mikityanskiy 
73794b51dae9SMat Martineau 	BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
73804b51dae9SMat Martineau 	       chan->rx_state);
73814b51dae9SMat Martineau 
73823aff8aacSMaxim Mikityanskiy 	if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
73834b51dae9SMat Martineau 		l2cap_pass_to_tx(chan, control);
73844b51dae9SMat Martineau 
738593917fd2SKai Ye 		BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
73864b51dae9SMat Martineau 		       __next_seq(chan, chan->buffer_seq));
73874b51dae9SMat Martineau 
73884b51dae9SMat Martineau 		chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
73894b51dae9SMat Martineau 
73904b51dae9SMat Martineau 		l2cap_reassemble_sdu(chan, skb, control);
73914b51dae9SMat Martineau 	} else {
73924b51dae9SMat Martineau 		if (chan->sdu) {
73934b51dae9SMat Martineau 			kfree_skb(chan->sdu);
73944b51dae9SMat Martineau 			chan->sdu = NULL;
73954b51dae9SMat Martineau 		}
73964b51dae9SMat Martineau 		chan->sdu_last_frag = NULL;
73974b51dae9SMat Martineau 		chan->sdu_len = 0;
73984b51dae9SMat Martineau 
73994b51dae9SMat Martineau 		if (skb) {
74004b51dae9SMat Martineau 			BT_DBG("Freeing %p", skb);
74014b51dae9SMat Martineau 			kfree_skb(skb);
74024b51dae9SMat Martineau 		}
74034b51dae9SMat Martineau 	}
74044b51dae9SMat Martineau 
74053aff8aacSMaxim Mikityanskiy 	chan->last_acked_seq = txseq;
74063aff8aacSMaxim Mikityanskiy 	chan->expected_tx_seq = __next_seq(chan, txseq);
74074b51dae9SMat Martineau 
74089a544210SPrasanna Karthik 	return 0;
7409cec8ab6eSMat Martineau }
7410cec8ab6eSMat Martineau 
7411cec8ab6eSMat Martineau static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7412cec8ab6eSMat Martineau {
7413a4368ff3SJohan Hedberg 	struct l2cap_ctrl *control = &bt_cb(skb)->l2cap;
7414cec8ab6eSMat Martineau 	u16 len;
7415cec8ab6eSMat Martineau 	u8 event;
74160a708f8fSGustavo F. Padovan 
7417b76bbd66SMat Martineau 	__unpack_control(chan, skb);
7418b76bbd66SMat Martineau 
74190a708f8fSGustavo F. Padovan 	len = skb->len;
74200a708f8fSGustavo F. Padovan 
74210a708f8fSGustavo F. Padovan 	/*
74220a708f8fSGustavo F. Padovan 	 * We can just drop the corrupted I-frame here.
74230a708f8fSGustavo F. Padovan 	 * Receiver will miss it and start proper recovery
7424cec8ab6eSMat Martineau 	 * procedures and ask for retransmission.
74250a708f8fSGustavo F. Padovan 	 */
742647d1ec61SGustavo F. Padovan 	if (l2cap_check_fcs(chan, skb))
74270a708f8fSGustavo F. Padovan 		goto drop;
74280a708f8fSGustavo F. Padovan 
7429cec8ab6eSMat Martineau 	if (!control->sframe && control->sar == L2CAP_SAR_START)
743003a51213SAndrei Emeltchenko 		len -= L2CAP_SDULEN_SIZE;
74310a708f8fSGustavo F. Padovan 
743247d1ec61SGustavo F. Padovan 	if (chan->fcs == L2CAP_FCS_CRC16)
743303a51213SAndrei Emeltchenko 		len -= L2CAP_FCS_SIZE;
74340a708f8fSGustavo F. Padovan 
743547d1ec61SGustavo F. Padovan 	if (len > chan->mps) {
74365e4e3972SAndrei Emeltchenko 		l2cap_send_disconn_req(chan, ECONNRESET);
74370a708f8fSGustavo F. Padovan 		goto drop;
74380a708f8fSGustavo F. Padovan 	}
74390a708f8fSGustavo F. Padovan 
7440f1942564SLuiz Augusto von Dentz 	if (chan->ops->filter) {
7441f1942564SLuiz Augusto von Dentz 		if (chan->ops->filter(chan, skb))
7442dbb50887SDaniel Borkmann 			goto drop;
7443f1942564SLuiz Augusto von Dentz 	}
7444dbb50887SDaniel Borkmann 
7445cec8ab6eSMat Martineau 	if (!control->sframe) {
7446cec8ab6eSMat Martineau 		int err;
74470a708f8fSGustavo F. Padovan 
7448cec8ab6eSMat Martineau 		BT_DBG("iframe sar %d, reqseq %d, final %d, txseq %d",
7449cec8ab6eSMat Martineau 		       control->sar, control->reqseq, control->final,
7450cec8ab6eSMat Martineau 		       control->txseq);
7451836be934SAndrei Emeltchenko 
7452cec8ab6eSMat Martineau 		/* Validate F-bit - F=0 always valid, F=1 only
7453cec8ab6eSMat Martineau 		 * valid in TX WAIT_F
7454cec8ab6eSMat Martineau 		 */
7455cec8ab6eSMat Martineau 		if (control->final && chan->tx_state != L2CAP_TX_STATE_WAIT_F)
74560a708f8fSGustavo F. Padovan 			goto drop;
74570a708f8fSGustavo F. Padovan 
7458cec8ab6eSMat Martineau 		if (chan->mode != L2CAP_MODE_STREAMING) {
7459cec8ab6eSMat Martineau 			event = L2CAP_EV_RECV_IFRAME;
7460cec8ab6eSMat Martineau 			err = l2cap_rx(chan, control, skb, event);
74610a708f8fSGustavo F. Padovan 		} else {
7462cec8ab6eSMat Martineau 			err = l2cap_stream_rx(chan, control, skb);
7463cec8ab6eSMat Martineau 		}
7464cec8ab6eSMat Martineau 
7465cec8ab6eSMat Martineau 		if (err)
74665e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
7467cec8ab6eSMat Martineau 	} else {
7468cec8ab6eSMat Martineau 		const u8 rx_func_to_event[4] = {
7469cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
7470cec8ab6eSMat Martineau 			L2CAP_EV_RECV_RNR, L2CAP_EV_RECV_SREJ
7471cec8ab6eSMat Martineau 		};
7472cec8ab6eSMat Martineau 
7473cec8ab6eSMat Martineau 		/* Only I-frames are expected in streaming mode */
7474cec8ab6eSMat Martineau 		if (chan->mode == L2CAP_MODE_STREAMING)
7475cec8ab6eSMat Martineau 			goto drop;
7476cec8ab6eSMat Martineau 
7477cec8ab6eSMat Martineau 		BT_DBG("sframe reqseq %d, final %d, poll %d, super %d",
7478cec8ab6eSMat Martineau 		       control->reqseq, control->final, control->poll,
7479cec8ab6eSMat Martineau 		       control->super);
7480cec8ab6eSMat Martineau 
74810a708f8fSGustavo F. Padovan 		if (len != 0) {
74821bb166e6SAndrei Emeltchenko 			BT_ERR("Trailing bytes: %d in sframe", len);
74835e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
74840a708f8fSGustavo F. Padovan 			goto drop;
74850a708f8fSGustavo F. Padovan 		}
74860a708f8fSGustavo F. Padovan 
7487cec8ab6eSMat Martineau 		/* Validate F and P bits */
7488cec8ab6eSMat Martineau 		if (control->final && (control->poll ||
7489cec8ab6eSMat Martineau 				       chan->tx_state != L2CAP_TX_STATE_WAIT_F))
7490cec8ab6eSMat Martineau 			goto drop;
7491cec8ab6eSMat Martineau 
7492cec8ab6eSMat Martineau 		event = rx_func_to_event[control->super];
7493cec8ab6eSMat Martineau 		if (l2cap_rx(chan, control, skb, event))
74945e4e3972SAndrei Emeltchenko 			l2cap_send_disconn_req(chan, ECONNRESET);
74950a708f8fSGustavo F. Padovan 	}
74960a708f8fSGustavo F. Padovan 
74970a708f8fSGustavo F. Padovan 	return 0;
74980a708f8fSGustavo F. Padovan 
74990a708f8fSGustavo F. Padovan drop:
75000a708f8fSGustavo F. Padovan 	kfree_skb(skb);
75010a708f8fSGustavo F. Padovan 	return 0;
75020a708f8fSGustavo F. Padovan }
75030a708f8fSGustavo F. Padovan 
7504b1c325c2SJohan Hedberg static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
7505b1c325c2SJohan Hedberg {
7506b1c325c2SJohan Hedberg 	struct l2cap_conn *conn = chan->conn;
7507b1c325c2SJohan Hedberg 	struct l2cap_le_credits pkt;
7508b1c325c2SJohan Hedberg 	u16 return_credits;
7509b1c325c2SJohan Hedberg 
751015f02b91SLuiz Augusto von Dentz 	return_credits = (chan->imtu / chan->mps) + 1;
7511b1c325c2SJohan Hedberg 
751215f02b91SLuiz Augusto von Dentz 	if (chan->rx_credits >= return_credits)
751396cd8eaaSLuiz Augusto von Dentz 		return;
7514b1c325c2SJohan Hedberg 
751515f02b91SLuiz Augusto von Dentz 	return_credits -= chan->rx_credits;
751615f02b91SLuiz Augusto von Dentz 
7517b1c325c2SJohan Hedberg 	BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
7518b1c325c2SJohan Hedberg 
7519b1c325c2SJohan Hedberg 	chan->rx_credits += return_credits;
7520b1c325c2SJohan Hedberg 
7521b1c325c2SJohan Hedberg 	pkt.cid     = cpu_to_le16(chan->scid);
7522b1c325c2SJohan Hedberg 	pkt.credits = cpu_to_le16(return_credits);
7523b1c325c2SJohan Hedberg 
7524b1c325c2SJohan Hedberg 	chan->ident = l2cap_get_ident(conn);
7525b1c325c2SJohan Hedberg 
7526b1c325c2SJohan Hedberg 	l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
7527b1c325c2SJohan Hedberg }
7528b1c325c2SJohan Hedberg 
752915f02b91SLuiz Augusto von Dentz static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
753096cd8eaaSLuiz Augusto von Dentz {
753196cd8eaaSLuiz Augusto von Dentz 	int err;
753296cd8eaaSLuiz Augusto von Dentz 
753396cd8eaaSLuiz Augusto von Dentz 	BT_DBG("SDU reassemble complete: chan %p skb->len %u", chan, skb->len);
753496cd8eaaSLuiz Augusto von Dentz 
753596cd8eaaSLuiz Augusto von Dentz 	/* Wait recv to confirm reception before updating the credits */
753696cd8eaaSLuiz Augusto von Dentz 	err = chan->ops->recv(chan, skb);
753796cd8eaaSLuiz Augusto von Dentz 
753896cd8eaaSLuiz Augusto von Dentz 	/* Update credits whenever an SDU is received */
753996cd8eaaSLuiz Augusto von Dentz 	l2cap_chan_le_send_credits(chan);
754096cd8eaaSLuiz Augusto von Dentz 
754196cd8eaaSLuiz Augusto von Dentz 	return err;
754296cd8eaaSLuiz Augusto von Dentz }
754396cd8eaaSLuiz Augusto von Dentz 
754415f02b91SLuiz Augusto von Dentz static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
7545fad5fc89SJohan Hedberg {
7546aac23bf6SJohan Hedberg 	int err;
7547fad5fc89SJohan Hedberg 
7548aac23bf6SJohan Hedberg 	if (!chan->rx_credits) {
7549aac23bf6SJohan Hedberg 		BT_ERR("No credits to receive LE L2CAP data");
7550dfd9774cSJohan Hedberg 		l2cap_send_disconn_req(chan, ECONNRESET);
7551fad5fc89SJohan Hedberg 		return -ENOBUFS;
7552aac23bf6SJohan Hedberg 	}
7553aac23bf6SJohan Hedberg 
7554aac23bf6SJohan Hedberg 	if (chan->imtu < skb->len) {
7555aac23bf6SJohan Hedberg 		BT_ERR("Too big LE L2CAP PDU");
7556aac23bf6SJohan Hedberg 		return -ENOBUFS;
7557aac23bf6SJohan Hedberg 	}
7558fad5fc89SJohan Hedberg 
7559fad5fc89SJohan Hedberg 	chan->rx_credits--;
7560fad5fc89SJohan Hedberg 	BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
7561fad5fc89SJohan Hedberg 
756296cd8eaaSLuiz Augusto von Dentz 	/* Update if remote had run out of credits, this should only happens
756396cd8eaaSLuiz Augusto von Dentz 	 * if the remote is not using the entire MPS.
756496cd8eaaSLuiz Augusto von Dentz 	 */
756596cd8eaaSLuiz Augusto von Dentz 	if (!chan->rx_credits)
7566fad5fc89SJohan Hedberg 		l2cap_chan_le_send_credits(chan);
7567fad5fc89SJohan Hedberg 
7568aac23bf6SJohan Hedberg 	err = 0;
7569aac23bf6SJohan Hedberg 
7570aac23bf6SJohan Hedberg 	if (!chan->sdu) {
7571aac23bf6SJohan Hedberg 		u16 sdu_len;
7572aac23bf6SJohan Hedberg 
7573aac23bf6SJohan Hedberg 		sdu_len = get_unaligned_le16(skb->data);
7574aac23bf6SJohan Hedberg 		skb_pull(skb, L2CAP_SDULEN_SIZE);
7575aac23bf6SJohan Hedberg 
7576aac23bf6SJohan Hedberg 		BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
7577aac23bf6SJohan Hedberg 		       sdu_len, skb->len, chan->imtu);
7578aac23bf6SJohan Hedberg 
7579aac23bf6SJohan Hedberg 		if (sdu_len > chan->imtu) {
7580aac23bf6SJohan Hedberg 			BT_ERR("Too big LE L2CAP SDU length received");
7581aac23bf6SJohan Hedberg 			err = -EMSGSIZE;
7582aac23bf6SJohan Hedberg 			goto failed;
7583aac23bf6SJohan Hedberg 		}
7584aac23bf6SJohan Hedberg 
7585aac23bf6SJohan Hedberg 		if (skb->len > sdu_len) {
7586aac23bf6SJohan Hedberg 			BT_ERR("Too much LE L2CAP data received");
7587aac23bf6SJohan Hedberg 			err = -EINVAL;
7588aac23bf6SJohan Hedberg 			goto failed;
7589aac23bf6SJohan Hedberg 		}
7590aac23bf6SJohan Hedberg 
7591aac23bf6SJohan Hedberg 		if (skb->len == sdu_len)
759215f02b91SLuiz Augusto von Dentz 			return l2cap_ecred_recv(chan, skb);
7593aac23bf6SJohan Hedberg 
7594aac23bf6SJohan Hedberg 		chan->sdu = skb;
7595aac23bf6SJohan Hedberg 		chan->sdu_len = sdu_len;
7596aac23bf6SJohan Hedberg 		chan->sdu_last_frag = skb;
7597aac23bf6SJohan Hedberg 
7598a5c3021bSLuiz Augusto von Dentz 		/* Detect if remote is not able to use the selected MPS */
7599a5c3021bSLuiz Augusto von Dentz 		if (skb->len + L2CAP_SDULEN_SIZE < chan->mps) {
7600a5c3021bSLuiz Augusto von Dentz 			u16 mps_len = skb->len + L2CAP_SDULEN_SIZE;
7601a5c3021bSLuiz Augusto von Dentz 
7602a5c3021bSLuiz Augusto von Dentz 			/* Adjust the number of credits */
7603a5c3021bSLuiz Augusto von Dentz 			BT_DBG("chan->mps %u -> %u", chan->mps, mps_len);
7604a5c3021bSLuiz Augusto von Dentz 			chan->mps = mps_len;
7605a5c3021bSLuiz Augusto von Dentz 			l2cap_chan_le_send_credits(chan);
7606a5c3021bSLuiz Augusto von Dentz 		}
7607a5c3021bSLuiz Augusto von Dentz 
7608aac23bf6SJohan Hedberg 		return 0;
7609aac23bf6SJohan Hedberg 	}
7610aac23bf6SJohan Hedberg 
7611aac23bf6SJohan Hedberg 	BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
7612aac23bf6SJohan Hedberg 	       chan->sdu->len, skb->len, chan->sdu_len);
7613aac23bf6SJohan Hedberg 
7614aac23bf6SJohan Hedberg 	if (chan->sdu->len + skb->len > chan->sdu_len) {
7615aac23bf6SJohan Hedberg 		BT_ERR("Too much LE L2CAP data received");
7616aac23bf6SJohan Hedberg 		err = -EINVAL;
7617aac23bf6SJohan Hedberg 		goto failed;
7618aac23bf6SJohan Hedberg 	}
7619aac23bf6SJohan Hedberg 
7620aac23bf6SJohan Hedberg 	append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
7621aac23bf6SJohan Hedberg 	skb = NULL;
7622aac23bf6SJohan Hedberg 
7623aac23bf6SJohan Hedberg 	if (chan->sdu->len == chan->sdu_len) {
762415f02b91SLuiz Augusto von Dentz 		err = l2cap_ecred_recv(chan, chan->sdu);
7625aac23bf6SJohan Hedberg 		if (!err) {
7626aac23bf6SJohan Hedberg 			chan->sdu = NULL;
7627aac23bf6SJohan Hedberg 			chan->sdu_last_frag = NULL;
7628aac23bf6SJohan Hedberg 			chan->sdu_len = 0;
7629aac23bf6SJohan Hedberg 		}
7630aac23bf6SJohan Hedberg 	}
7631aac23bf6SJohan Hedberg 
7632aac23bf6SJohan Hedberg failed:
7633aac23bf6SJohan Hedberg 	if (err) {
7634aac23bf6SJohan Hedberg 		kfree_skb(skb);
7635aac23bf6SJohan Hedberg 		kfree_skb(chan->sdu);
7636aac23bf6SJohan Hedberg 		chan->sdu = NULL;
7637aac23bf6SJohan Hedberg 		chan->sdu_last_frag = NULL;
7638aac23bf6SJohan Hedberg 		chan->sdu_len = 0;
7639aac23bf6SJohan Hedberg 	}
7640aac23bf6SJohan Hedberg 
7641aac23bf6SJohan Hedberg 	/* We can't return an error here since we took care of the skb
7642aac23bf6SJohan Hedberg 	 * freeing internally. An error return would cause the caller to
7643aac23bf6SJohan Hedberg 	 * do a double-free of the skb.
7644aac23bf6SJohan Hedberg 	 */
7645aac23bf6SJohan Hedberg 	return 0;
7646fad5fc89SJohan Hedberg }
7647fad5fc89SJohan Hedberg 
764813ca56e0SAndrei Emeltchenko static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
764913ca56e0SAndrei Emeltchenko 			       struct sk_buff *skb)
76500a708f8fSGustavo F. Padovan {
765148454079SGustavo F. Padovan 	struct l2cap_chan *chan;
76520a708f8fSGustavo F. Padovan 
7653baa7e1faSGustavo F. Padovan 	chan = l2cap_get_chan_by_scid(conn, cid);
765448454079SGustavo F. Padovan 	if (!chan) {
765597e8e89dSAndrei Emeltchenko 		if (cid == L2CAP_CID_A2MP) {
765697e8e89dSAndrei Emeltchenko 			chan = a2mp_channel_create(conn, skb);
765797e8e89dSAndrei Emeltchenko 			if (!chan) {
765897e8e89dSAndrei Emeltchenko 				kfree_skb(skb);
765913ca56e0SAndrei Emeltchenko 				return;
766097e8e89dSAndrei Emeltchenko 			}
766197e8e89dSAndrei Emeltchenko 
76620d0e2d03SZhengchao Shao 			l2cap_chan_hold(chan);
766397e8e89dSAndrei Emeltchenko 			l2cap_chan_lock(chan);
766497e8e89dSAndrei Emeltchenko 		} else {
76650a708f8fSGustavo F. Padovan 			BT_DBG("unknown cid 0x%4.4x", cid);
76666be36555SAndrei Emeltchenko 			/* Drop packet and return */
76673379013bSDan Carpenter 			kfree_skb(skb);
766813ca56e0SAndrei Emeltchenko 			return;
76690a708f8fSGustavo F. Padovan 		}
767097e8e89dSAndrei Emeltchenko 	}
76710a708f8fSGustavo F. Padovan 
767249208c9cSGustavo F. Padovan 	BT_DBG("chan %p, len %d", chan, skb->len);
76730a708f8fSGustavo F. Padovan 
7674315917e0SJohan Hedberg 	/* If we receive data on a fixed channel before the info req/rsp
76755153ceb9SBhaskar Chowdhury 	 * procedure is done simply assume that the channel is supported
7676315917e0SJohan Hedberg 	 * and mark it as ready.
7677315917e0SJohan Hedberg 	 */
7678315917e0SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED)
7679315917e0SJohan Hedberg 		l2cap_chan_ready(chan);
7680315917e0SJohan Hedberg 
768189bc500eSGustavo F. Padovan 	if (chan->state != BT_CONNECTED)
76820a708f8fSGustavo F. Padovan 		goto drop;
76830a708f8fSGustavo F. Padovan 
76840c1bc5c6SGustavo F. Padovan 	switch (chan->mode) {
768538319713SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
768615f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
768715f02b91SLuiz Augusto von Dentz 		if (l2cap_ecred_data_rcv(chan, skb) < 0)
7688fad5fc89SJohan Hedberg 			goto drop;
7689fad5fc89SJohan Hedberg 
7690fad5fc89SJohan Hedberg 		goto done;
7691fad5fc89SJohan Hedberg 
76920a708f8fSGustavo F. Padovan 	case L2CAP_MODE_BASIC:
76930a708f8fSGustavo F. Padovan 		/* If socket recv buffers overflows we drop data here
76940a708f8fSGustavo F. Padovan 		 * which is *bad* because L2CAP has to be reliable.
76950a708f8fSGustavo F. Padovan 		 * But we don't have any other choice. L2CAP doesn't
76960a708f8fSGustavo F. Padovan 		 * provide flow control mechanism. */
76970a708f8fSGustavo F. Padovan 
76982c96e03dSSzymon Janc 		if (chan->imtu < skb->len) {
76992c96e03dSSzymon Janc 			BT_ERR("Dropping L2CAP data: receive buffer overflow");
77000a708f8fSGustavo F. Padovan 			goto drop;
77012c96e03dSSzymon Janc 		}
77020a708f8fSGustavo F. Padovan 
770380b98027SGustavo Padovan 		if (!chan->ops->recv(chan, skb))
77040a708f8fSGustavo F. Padovan 			goto done;
77050a708f8fSGustavo F. Padovan 		break;
77060a708f8fSGustavo F. Padovan 
77070a708f8fSGustavo F. Padovan 	case L2CAP_MODE_ERTM:
77080a708f8fSGustavo F. Padovan 	case L2CAP_MODE_STREAMING:
7709cec8ab6eSMat Martineau 		l2cap_data_rcv(chan, skb);
77100a708f8fSGustavo F. Padovan 		goto done;
77110a708f8fSGustavo F. Padovan 
77120a708f8fSGustavo F. Padovan 	default:
77130c1bc5c6SGustavo F. Padovan 		BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
77140a708f8fSGustavo F. Padovan 		break;
77150a708f8fSGustavo F. Padovan 	}
77160a708f8fSGustavo F. Padovan 
77170a708f8fSGustavo F. Padovan drop:
77180a708f8fSGustavo F. Padovan 	kfree_skb(skb);
77190a708f8fSGustavo F. Padovan 
77200a708f8fSGustavo F. Padovan done:
77216be36555SAndrei Emeltchenko 	l2cap_chan_unlock(chan);
7722d0be8347SLuiz Augusto von Dentz 	l2cap_chan_put(chan);
77230a708f8fSGustavo F. Padovan }
77240a708f8fSGustavo F. Padovan 
772584104b24SAndrei Emeltchenko static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
772684104b24SAndrei Emeltchenko 				  struct sk_buff *skb)
77270a708f8fSGustavo F. Padovan {
7728ae4fd2d3SMarcel Holtmann 	struct hci_conn *hcon = conn->hcon;
772923691d75SGustavo F. Padovan 	struct l2cap_chan *chan;
77300a708f8fSGustavo F. Padovan 
7731ae4fd2d3SMarcel Holtmann 	if (hcon->type != ACL_LINK)
7732a24cce14SJohan Hedberg 		goto free_skb;
7733ae4fd2d3SMarcel Holtmann 
7734bf20fd4eSJohan Hedberg 	chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
7735bf20fd4eSJohan Hedberg 					ACL_LINK);
773623691d75SGustavo F. Padovan 	if (!chan)
7737a24cce14SJohan Hedberg 		goto free_skb;
77380a708f8fSGustavo F. Padovan 
77395b4cedaaSAndrei Emeltchenko 	BT_DBG("chan %p, len %d", chan, skb->len);
77400a708f8fSGustavo F. Padovan 
774189bc500eSGustavo F. Padovan 	if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
77420a708f8fSGustavo F. Padovan 		goto drop;
77430a708f8fSGustavo F. Padovan 
7744e13e21dcSVinicius Costa Gomes 	if (chan->imtu < skb->len)
77450a708f8fSGustavo F. Padovan 		goto drop;
77460a708f8fSGustavo F. Padovan 
77472edf870dSMarcel Holtmann 	/* Store remote BD_ADDR and PSM for msg_name */
7748a4368ff3SJohan Hedberg 	bacpy(&bt_cb(skb)->l2cap.bdaddr, &hcon->dst);
7749a4368ff3SJohan Hedberg 	bt_cb(skb)->l2cap.psm = psm;
77502edf870dSMarcel Holtmann 
7751a24cce14SJohan Hedberg 	if (!chan->ops->recv(chan, skb)) {
7752a24cce14SJohan Hedberg 		l2cap_chan_put(chan);
775384104b24SAndrei Emeltchenko 		return;
7754a24cce14SJohan Hedberg 	}
77550a708f8fSGustavo F. Padovan 
77560a708f8fSGustavo F. Padovan drop:
7757a24cce14SJohan Hedberg 	l2cap_chan_put(chan);
7758a24cce14SJohan Hedberg free_skb:
77590a708f8fSGustavo F. Padovan 	kfree_skb(skb);
77600a708f8fSGustavo F. Padovan }
77610a708f8fSGustavo F. Padovan 
77620a708f8fSGustavo F. Padovan static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
77630a708f8fSGustavo F. Padovan {
77640a708f8fSGustavo F. Padovan 	struct l2cap_hdr *lh = (void *) skb->data;
776561a939c6SJohan Hedberg 	struct hci_conn *hcon = conn->hcon;
77660a708f8fSGustavo F. Padovan 	u16 cid, len;
77670a708f8fSGustavo F. Padovan 	__le16 psm;
77680a708f8fSGustavo F. Padovan 
776961a939c6SJohan Hedberg 	if (hcon->state != BT_CONNECTED) {
777061a939c6SJohan Hedberg 		BT_DBG("queueing pending rx skb");
777161a939c6SJohan Hedberg 		skb_queue_tail(&conn->pending_rx, skb);
777261a939c6SJohan Hedberg 		return;
777361a939c6SJohan Hedberg 	}
777461a939c6SJohan Hedberg 
77750a708f8fSGustavo F. Padovan 	skb_pull(skb, L2CAP_HDR_SIZE);
77760a708f8fSGustavo F. Padovan 	cid = __le16_to_cpu(lh->cid);
77770a708f8fSGustavo F. Padovan 	len = __le16_to_cpu(lh->len);
77780a708f8fSGustavo F. Padovan 
77790a708f8fSGustavo F. Padovan 	if (len != skb->len) {
77800a708f8fSGustavo F. Padovan 		kfree_skb(skb);
77810a708f8fSGustavo F. Padovan 		return;
77820a708f8fSGustavo F. Padovan 	}
77830a708f8fSGustavo F. Padovan 
77849e1d7e15SJohan Hedberg 	/* Since we can't actively block incoming LE connections we must
77859e1d7e15SJohan Hedberg 	 * at least ensure that we ignore incoming data from them.
77869e1d7e15SJohan Hedberg 	 */
77879e1d7e15SJohan Hedberg 	if (hcon->type == LE_LINK &&
77883d4f9c00SArchie Pusaka 	    hci_bdaddr_list_lookup(&hcon->hdev->reject_list, &hcon->dst,
7789a250e048SJohan Hedberg 				   bdaddr_dst_type(hcon))) {
7790e493150eSJohan Hedberg 		kfree_skb(skb);
7791e493150eSJohan Hedberg 		return;
7792e493150eSJohan Hedberg 	}
7793e493150eSJohan Hedberg 
77940a708f8fSGustavo F. Padovan 	BT_DBG("len %d, cid 0x%4.4x", len, cid);
77950a708f8fSGustavo F. Padovan 
77960a708f8fSGustavo F. Padovan 	switch (cid) {
77970a708f8fSGustavo F. Padovan 	case L2CAP_CID_SIGNALING:
77980a708f8fSGustavo F. Padovan 		l2cap_sig_channel(conn, skb);
77990a708f8fSGustavo F. Padovan 		break;
78000a708f8fSGustavo F. Padovan 
78010a708f8fSGustavo F. Padovan 	case L2CAP_CID_CONN_LESS:
7802097db76cSAndrei Emeltchenko 		psm = get_unaligned((__le16 *) skb->data);
78030181a70fSAndrei Emeltchenko 		skb_pull(skb, L2CAP_PSMLEN_SIZE);
78040a708f8fSGustavo F. Padovan 		l2cap_conless_channel(conn, psm, skb);
78050a708f8fSGustavo F. Padovan 		break;
78060a708f8fSGustavo F. Padovan 
7807a2877629SMarcel Holtmann 	case L2CAP_CID_LE_SIGNALING:
7808a2877629SMarcel Holtmann 		l2cap_le_sig_channel(conn, skb);
7809a2877629SMarcel Holtmann 		break;
7810a2877629SMarcel Holtmann 
78110a708f8fSGustavo F. Padovan 	default:
78120a708f8fSGustavo F. Padovan 		l2cap_data_channel(conn, cid, skb);
78130a708f8fSGustavo F. Padovan 		break;
78140a708f8fSGustavo F. Padovan 	}
78150a708f8fSGustavo F. Padovan }
78160a708f8fSGustavo F. Padovan 
781761a939c6SJohan Hedberg static void process_pending_rx(struct work_struct *work)
781861a939c6SJohan Hedberg {
781961a939c6SJohan Hedberg 	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
782061a939c6SJohan Hedberg 					       pending_rx_work);
782161a939c6SJohan Hedberg 	struct sk_buff *skb;
782261a939c6SJohan Hedberg 
782361a939c6SJohan Hedberg 	BT_DBG("");
782461a939c6SJohan Hedberg 
782561a939c6SJohan Hedberg 	while ((skb = skb_dequeue(&conn->pending_rx)))
782661a939c6SJohan Hedberg 		l2cap_recv_frame(conn, skb);
782761a939c6SJohan Hedberg }
782861a939c6SJohan Hedberg 
7829162b49e7SJohan Hedberg static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
7830162b49e7SJohan Hedberg {
7831162b49e7SJohan Hedberg 	struct l2cap_conn *conn = hcon->l2cap_data;
7832162b49e7SJohan Hedberg 	struct hci_chan *hchan;
7833162b49e7SJohan Hedberg 
7834162b49e7SJohan Hedberg 	if (conn)
7835162b49e7SJohan Hedberg 		return conn;
7836162b49e7SJohan Hedberg 
7837162b49e7SJohan Hedberg 	hchan = hci_chan_create(hcon);
7838162b49e7SJohan Hedberg 	if (!hchan)
7839162b49e7SJohan Hedberg 		return NULL;
7840162b49e7SJohan Hedberg 
784127f70f3eSJohan Hedberg 	conn = kzalloc(sizeof(*conn), GFP_KERNEL);
7842162b49e7SJohan Hedberg 	if (!conn) {
7843162b49e7SJohan Hedberg 		hci_chan_del(hchan);
7844162b49e7SJohan Hedberg 		return NULL;
7845162b49e7SJohan Hedberg 	}
7846162b49e7SJohan Hedberg 
7847162b49e7SJohan Hedberg 	kref_init(&conn->ref);
7848162b49e7SJohan Hedberg 	hcon->l2cap_data = conn;
784951bb8457SJohan Hedberg 	conn->hcon = hci_conn_get(hcon);
7850162b49e7SJohan Hedberg 	conn->hchan = hchan;
7851162b49e7SJohan Hedberg 
7852162b49e7SJohan Hedberg 	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
7853162b49e7SJohan Hedberg 
7854162b49e7SJohan Hedberg 	switch (hcon->type) {
7855162b49e7SJohan Hedberg 	case LE_LINK:
7856162b49e7SJohan Hedberg 		if (hcon->hdev->le_mtu) {
7857162b49e7SJohan Hedberg 			conn->mtu = hcon->hdev->le_mtu;
7858162b49e7SJohan Hedberg 			break;
7859162b49e7SJohan Hedberg 		}
786019186c7bSGustavo A. R. Silva 		fallthrough;
7861162b49e7SJohan Hedberg 	default:
7862162b49e7SJohan Hedberg 		conn->mtu = hcon->hdev->acl_mtu;
7863162b49e7SJohan Hedberg 		break;
7864162b49e7SJohan Hedberg 	}
7865162b49e7SJohan Hedberg 
7866162b49e7SJohan Hedberg 	conn->feat_mask = 0;
7867162b49e7SJohan Hedberg 
78680bd49fc7SJohan Hedberg 	conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
78690bd49fc7SJohan Hedberg 
78700bd49fc7SJohan Hedberg 	if (hcon->type == ACL_LINK &&
7871d7a5a11dSMarcel Holtmann 	    hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
78720bd49fc7SJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_A2MP;
7873162b49e7SJohan Hedberg 
7874d7a5a11dSMarcel Holtmann 	if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
7875f9be9e86SMarcel Holtmann 	    (bredr_sc_enabled(hcon->hdev) ||
7876b7cb93e5SMarcel Holtmann 	     hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
7877b5ae344dSJohan Hedberg 		conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
7878b5ae344dSJohan Hedberg 
78795a54e7c8SMarcel Holtmann 	mutex_init(&conn->ident_lock);
7880162b49e7SJohan Hedberg 	mutex_init(&conn->chan_lock);
7881162b49e7SJohan Hedberg 
7882162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->chan_l);
7883162b49e7SJohan Hedberg 	INIT_LIST_HEAD(&conn->users);
7884162b49e7SJohan Hedberg 
7885162b49e7SJohan Hedberg 	INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
7886162b49e7SJohan Hedberg 
788761a939c6SJohan Hedberg 	skb_queue_head_init(&conn->pending_rx);
788861a939c6SJohan Hedberg 	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
7889f3d82d0cSJohan Hedberg 	INIT_WORK(&conn->id_addr_update_work, l2cap_conn_update_id_addr);
789061a939c6SJohan Hedberg 
7891162b49e7SJohan Hedberg 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
7892162b49e7SJohan Hedberg 
7893162b49e7SJohan Hedberg 	return conn;
7894162b49e7SJohan Hedberg }
7895162b49e7SJohan Hedberg 
7896149b3f13SMeng Yu static bool is_valid_psm(u16 psm, u8 dst_type)
7897149b3f13SMeng Yu {
7898162b49e7SJohan Hedberg 	if (!psm)
7899162b49e7SJohan Hedberg 		return false;
7900162b49e7SJohan Hedberg 
7901162b49e7SJohan Hedberg 	if (bdaddr_type_is_le(dst_type))
7902162b49e7SJohan Hedberg 		return (psm <= 0x00ff);
7903162b49e7SJohan Hedberg 
7904162b49e7SJohan Hedberg 	/* PSM must be odd and lsb of upper byte must be 0 */
7905162b49e7SJohan Hedberg 	return ((psm & 0x0101) == 0x0001);
7906162b49e7SJohan Hedberg }
7907162b49e7SJohan Hedberg 
7908da49b602SLuiz Augusto von Dentz struct l2cap_chan_data {
7909da49b602SLuiz Augusto von Dentz 	struct l2cap_chan *chan;
7910da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7911da49b602SLuiz Augusto von Dentz 	int count;
7912da49b602SLuiz Augusto von Dentz };
7913da49b602SLuiz Augusto von Dentz 
7914da49b602SLuiz Augusto von Dentz static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
7915da49b602SLuiz Augusto von Dentz {
7916da49b602SLuiz Augusto von Dentz 	struct l2cap_chan_data *d = data;
7917da49b602SLuiz Augusto von Dentz 	struct pid *pid;
7918da49b602SLuiz Augusto von Dentz 
7919da49b602SLuiz Augusto von Dentz 	if (chan == d->chan)
7920da49b602SLuiz Augusto von Dentz 		return;
7921da49b602SLuiz Augusto von Dentz 
7922da49b602SLuiz Augusto von Dentz 	if (!test_bit(FLAG_DEFER_SETUP, &chan->flags))
7923da49b602SLuiz Augusto von Dentz 		return;
7924da49b602SLuiz Augusto von Dentz 
7925da49b602SLuiz Augusto von Dentz 	pid = chan->ops->get_peer_pid(chan);
7926da49b602SLuiz Augusto von Dentz 
7927da49b602SLuiz Augusto von Dentz 	/* Only count deferred channels with the same PID/PSM */
7928da49b602SLuiz Augusto von Dentz 	if (d->pid != pid || chan->psm != d->chan->psm || chan->ident ||
7929da49b602SLuiz Augusto von Dentz 	    chan->mode != L2CAP_MODE_EXT_FLOWCTL || chan->state != BT_CONNECT)
7930da49b602SLuiz Augusto von Dentz 		return;
7931da49b602SLuiz Augusto von Dentz 
7932da49b602SLuiz Augusto von Dentz 	d->count++;
7933da49b602SLuiz Augusto von Dentz }
7934da49b602SLuiz Augusto von Dentz 
7935162b49e7SJohan Hedberg int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
7936162b49e7SJohan Hedberg 		       bdaddr_t *dst, u8 dst_type)
7937162b49e7SJohan Hedberg {
7938162b49e7SJohan Hedberg 	struct l2cap_conn *conn;
7939162b49e7SJohan Hedberg 	struct hci_conn *hcon;
7940162b49e7SJohan Hedberg 	struct hci_dev *hdev;
7941162b49e7SJohan Hedberg 	int err;
7942162b49e7SJohan Hedberg 
794315f02b91SLuiz Augusto von Dentz 	BT_DBG("%pMR -> %pMR (type %u) psm 0x%4.4x mode 0x%2.2x", &chan->src,
794415f02b91SLuiz Augusto von Dentz 	       dst, dst_type, __le16_to_cpu(psm), chan->mode);
7945162b49e7SJohan Hedberg 
794639385cb5SJohan Hedberg 	hdev = hci_get_route(dst, &chan->src, chan->src_type);
7947162b49e7SJohan Hedberg 	if (!hdev)
7948162b49e7SJohan Hedberg 		return -EHOSTUNREACH;
7949162b49e7SJohan Hedberg 
7950162b49e7SJohan Hedberg 	hci_dev_lock(hdev);
7951162b49e7SJohan Hedberg 
7952162b49e7SJohan Hedberg 	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
7953162b49e7SJohan Hedberg 	    chan->chan_type != L2CAP_CHAN_RAW) {
7954162b49e7SJohan Hedberg 		err = -EINVAL;
7955162b49e7SJohan Hedberg 		goto done;
7956162b49e7SJohan Hedberg 	}
7957162b49e7SJohan Hedberg 
795821626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) {
795921626e62SJohan Hedberg 		err = -EINVAL;
796021626e62SJohan Hedberg 		goto done;
796121626e62SJohan Hedberg 	}
796221626e62SJohan Hedberg 
796321626e62SJohan Hedberg 	if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) {
7964162b49e7SJohan Hedberg 		err = -EINVAL;
7965162b49e7SJohan Hedberg 		goto done;
7966162b49e7SJohan Hedberg 	}
7967162b49e7SJohan Hedberg 
7968162b49e7SJohan Hedberg 	switch (chan->mode) {
7969162b49e7SJohan Hedberg 	case L2CAP_MODE_BASIC:
7970162b49e7SJohan Hedberg 		break;
7971162b49e7SJohan Hedberg 	case L2CAP_MODE_LE_FLOWCTL:
79724be5ca67SLuiz Augusto von Dentz 		break;
797315f02b91SLuiz Augusto von Dentz 	case L2CAP_MODE_EXT_FLOWCTL:
79744be5ca67SLuiz Augusto von Dentz 		if (!enable_ecred) {
79754be5ca67SLuiz Augusto von Dentz 			err = -EOPNOTSUPP;
79764be5ca67SLuiz Augusto von Dentz 			goto done;
79774be5ca67SLuiz Augusto von Dentz 		}
7978162b49e7SJohan Hedberg 		break;
7979162b49e7SJohan Hedberg 	case L2CAP_MODE_ERTM:
7980162b49e7SJohan Hedberg 	case L2CAP_MODE_STREAMING:
7981162b49e7SJohan Hedberg 		if (!disable_ertm)
7982162b49e7SJohan Hedberg 			break;
798319186c7bSGustavo A. R. Silva 		fallthrough;
7984162b49e7SJohan Hedberg 	default:
7985beb19e4cSJohan Hedberg 		err = -EOPNOTSUPP;
7986162b49e7SJohan Hedberg 		goto done;
7987162b49e7SJohan Hedberg 	}
7988162b49e7SJohan Hedberg 
7989162b49e7SJohan Hedberg 	switch (chan->state) {
7990162b49e7SJohan Hedberg 	case BT_CONNECT:
7991162b49e7SJohan Hedberg 	case BT_CONNECT2:
7992162b49e7SJohan Hedberg 	case BT_CONFIG:
7993162b49e7SJohan Hedberg 		/* Already connecting */
7994162b49e7SJohan Hedberg 		err = 0;
7995162b49e7SJohan Hedberg 		goto done;
7996162b49e7SJohan Hedberg 
7997162b49e7SJohan Hedberg 	case BT_CONNECTED:
7998162b49e7SJohan Hedberg 		/* Already connected */
7999162b49e7SJohan Hedberg 		err = -EISCONN;
8000162b49e7SJohan Hedberg 		goto done;
8001162b49e7SJohan Hedberg 
8002162b49e7SJohan Hedberg 	case BT_OPEN:
8003162b49e7SJohan Hedberg 	case BT_BOUND:
8004162b49e7SJohan Hedberg 		/* Can connect */
8005162b49e7SJohan Hedberg 		break;
8006162b49e7SJohan Hedberg 
8007162b49e7SJohan Hedberg 	default:
8008162b49e7SJohan Hedberg 		err = -EBADFD;
8009162b49e7SJohan Hedberg 		goto done;
8010162b49e7SJohan Hedberg 	}
8011162b49e7SJohan Hedberg 
8012162b49e7SJohan Hedberg 	/* Set destination address and psm */
8013162b49e7SJohan Hedberg 	bacpy(&chan->dst, dst);
8014162b49e7SJohan Hedberg 	chan->dst_type = dst_type;
8015162b49e7SJohan Hedberg 
8016162b49e7SJohan Hedberg 	chan->psm = psm;
8017162b49e7SJohan Hedberg 	chan->dcid = cid;
8018162b49e7SJohan Hedberg 
80196f77d8c7SAndre Guedes 	if (bdaddr_type_is_le(dst_type)) {
80206f77d8c7SAndre Guedes 		/* Convert from L2CAP channel address type to HCI address type
80216f77d8c7SAndre Guedes 		 */
80226f77d8c7SAndre Guedes 		if (dst_type == BDADDR_LE_PUBLIC)
80236f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_PUBLIC;
80246f77d8c7SAndre Guedes 		else
80256f77d8c7SAndre Guedes 			dst_type = ADDR_LE_DEV_RANDOM;
80266f77d8c7SAndre Guedes 
8027d7a5a11dSMarcel Holtmann 		if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
8028d850bf08SLuiz Augusto von Dentz 			hcon = hci_connect_le(hdev, dst, dst_type, false,
8029fa142220SJakub Pawlowski 					      chan->sec_level,
8030fa142220SJakub Pawlowski 					      HCI_LE_CONN_TIMEOUT,
80318e8b92eeSLuiz Augusto von Dentz 					      HCI_ROLE_SLAVE);
80320ad06aa6SJohan Hedberg 		else
80330ad06aa6SJohan Hedberg 			hcon = hci_connect_le_scan(hdev, dst, dst_type,
80340ad06aa6SJohan Hedberg 						   chan->sec_level,
803576b13996SManish Mandlik 						   HCI_LE_CONN_TIMEOUT,
803676b13996SManish Mandlik 						   CONN_REASON_L2CAP_CHAN);
80370ad06aa6SJohan Hedberg 
80386f77d8c7SAndre Guedes 	} else {
8039d93375a8SJohan Hedberg 		u8 auth_type = l2cap_get_auth_type(chan);
804076b13996SManish Mandlik 		hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
804176b13996SManish Mandlik 				       CONN_REASON_L2CAP_CHAN);
80426f77d8c7SAndre Guedes 	}
8043162b49e7SJohan Hedberg 
8044162b49e7SJohan Hedberg 	if (IS_ERR(hcon)) {
8045162b49e7SJohan Hedberg 		err = PTR_ERR(hcon);
8046162b49e7SJohan Hedberg 		goto done;
8047162b49e7SJohan Hedberg 	}
8048162b49e7SJohan Hedberg 
8049162b49e7SJohan Hedberg 	conn = l2cap_conn_add(hcon);
8050162b49e7SJohan Hedberg 	if (!conn) {
8051162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
8052162b49e7SJohan Hedberg 		err = -ENOMEM;
8053162b49e7SJohan Hedberg 		goto done;
8054162b49e7SJohan Hedberg 	}
8055162b49e7SJohan Hedberg 
8056da49b602SLuiz Augusto von Dentz 	if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) {
8057da49b602SLuiz Augusto von Dentz 		struct l2cap_chan_data data;
8058da49b602SLuiz Augusto von Dentz 
8059da49b602SLuiz Augusto von Dentz 		data.chan = chan;
8060da49b602SLuiz Augusto von Dentz 		data.pid = chan->ops->get_peer_pid(chan);
8061da49b602SLuiz Augusto von Dentz 		data.count = 1;
8062da49b602SLuiz Augusto von Dentz 
8063da49b602SLuiz Augusto von Dentz 		l2cap_chan_list(conn, l2cap_chan_by_pid, &data);
8064da49b602SLuiz Augusto von Dentz 
8065da49b602SLuiz Augusto von Dentz 		/* Check if there isn't too many channels being connected */
8066da49b602SLuiz Augusto von Dentz 		if (data.count > L2CAP_ECRED_CONN_SCID_MAX) {
8067da49b602SLuiz Augusto von Dentz 			hci_conn_drop(hcon);
8068da49b602SLuiz Augusto von Dentz 			err = -EPROTO;
8069da49b602SLuiz Augusto von Dentz 			goto done;
8070da49b602SLuiz Augusto von Dentz 		}
8071da49b602SLuiz Augusto von Dentz 	}
8072da49b602SLuiz Augusto von Dentz 
807302e246aeSJohan Hedberg 	mutex_lock(&conn->chan_lock);
807402e246aeSJohan Hedberg 	l2cap_chan_lock(chan);
807502e246aeSJohan Hedberg 
8076162b49e7SJohan Hedberg 	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
8077162b49e7SJohan Hedberg 		hci_conn_drop(hcon);
8078162b49e7SJohan Hedberg 		err = -EBUSY;
807902e246aeSJohan Hedberg 		goto chan_unlock;
8080162b49e7SJohan Hedberg 	}
8081162b49e7SJohan Hedberg 
8082162b49e7SJohan Hedberg 	/* Update source addr of the socket */
8083162b49e7SJohan Hedberg 	bacpy(&chan->src, &hcon->src);
8084a250e048SJohan Hedberg 	chan->src_type = bdaddr_src_type(hcon);
8085162b49e7SJohan Hedberg 
808602e246aeSJohan Hedberg 	__l2cap_chan_add(conn, chan);
8087162b49e7SJohan Hedberg 
8088162b49e7SJohan Hedberg 	/* l2cap_chan_add takes its own ref so we can drop this one */
8089162b49e7SJohan Hedberg 	hci_conn_drop(hcon);
8090162b49e7SJohan Hedberg 
8091162b49e7SJohan Hedberg 	l2cap_state_change(chan, BT_CONNECT);
8092162b49e7SJohan Hedberg 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
8093162b49e7SJohan Hedberg 
809461202e4dSJohan Hedberg 	/* Release chan->sport so that it can be reused by other
809561202e4dSJohan Hedberg 	 * sockets (as it's only used for listening sockets).
809661202e4dSJohan Hedberg 	 */
809761202e4dSJohan Hedberg 	write_lock(&chan_list_lock);
809861202e4dSJohan Hedberg 	chan->sport = 0;
809961202e4dSJohan Hedberg 	write_unlock(&chan_list_lock);
810061202e4dSJohan Hedberg 
8101162b49e7SJohan Hedberg 	if (hcon->state == BT_CONNECTED) {
8102162b49e7SJohan Hedberg 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
8103162b49e7SJohan Hedberg 			__clear_chan_timer(chan);
8104e7cafc45SJohan Hedberg 			if (l2cap_chan_check_security(chan, true))
8105162b49e7SJohan Hedberg 				l2cap_state_change(chan, BT_CONNECTED);
8106162b49e7SJohan Hedberg 		} else
8107162b49e7SJohan Hedberg 			l2cap_do_start(chan);
8108162b49e7SJohan Hedberg 	}
8109162b49e7SJohan Hedberg 
8110162b49e7SJohan Hedberg 	err = 0;
8111162b49e7SJohan Hedberg 
811202e246aeSJohan Hedberg chan_unlock:
8113162b49e7SJohan Hedberg 	l2cap_chan_unlock(chan);
811402e246aeSJohan Hedberg 	mutex_unlock(&conn->chan_lock);
811502e246aeSJohan Hedberg done:
8116162b49e7SJohan Hedberg 	hci_dev_unlock(hdev);
8117162b49e7SJohan Hedberg 	hci_dev_put(hdev);
8118162b49e7SJohan Hedberg 	return err;
8119162b49e7SJohan Hedberg }
81206b8d4a6aSJukka Rissanen EXPORT_SYMBOL_GPL(l2cap_chan_connect);
8121162b49e7SJohan Hedberg 
812215f02b91SLuiz Augusto von Dentz static void l2cap_ecred_reconfigure(struct l2cap_chan *chan)
812315f02b91SLuiz Augusto von Dentz {
812415f02b91SLuiz Augusto von Dentz 	struct l2cap_conn *conn = chan->conn;
812515f02b91SLuiz Augusto von Dentz 	struct {
812615f02b91SLuiz Augusto von Dentz 		struct l2cap_ecred_reconf_req req;
812715f02b91SLuiz Augusto von Dentz 		__le16 scid;
812815f02b91SLuiz Augusto von Dentz 	} pdu;
812915f02b91SLuiz Augusto von Dentz 
813015f02b91SLuiz Augusto von Dentz 	pdu.req.mtu = cpu_to_le16(chan->imtu);
813115f02b91SLuiz Augusto von Dentz 	pdu.req.mps = cpu_to_le16(chan->mps);
813215f02b91SLuiz Augusto von Dentz 	pdu.scid    = cpu_to_le16(chan->scid);
813315f02b91SLuiz Augusto von Dentz 
813415f02b91SLuiz Augusto von Dentz 	chan->ident = l2cap_get_ident(conn);
813515f02b91SLuiz Augusto von Dentz 
813615f02b91SLuiz Augusto von Dentz 	l2cap_send_cmd(conn, chan->ident, L2CAP_ECRED_RECONF_REQ,
813715f02b91SLuiz Augusto von Dentz 		       sizeof(pdu), &pdu);
813815f02b91SLuiz Augusto von Dentz }
813915f02b91SLuiz Augusto von Dentz 
814015f02b91SLuiz Augusto von Dentz int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu)
814115f02b91SLuiz Augusto von Dentz {
814215f02b91SLuiz Augusto von Dentz 	if (chan->imtu > mtu)
814315f02b91SLuiz Augusto von Dentz 		return -EINVAL;
814415f02b91SLuiz Augusto von Dentz 
814515f02b91SLuiz Augusto von Dentz 	BT_DBG("chan %p mtu 0x%4.4x", chan, mtu);
814615f02b91SLuiz Augusto von Dentz 
814715f02b91SLuiz Augusto von Dentz 	chan->imtu = mtu;
814815f02b91SLuiz Augusto von Dentz 
814915f02b91SLuiz Augusto von Dentz 	l2cap_ecred_reconfigure(chan);
815015f02b91SLuiz Augusto von Dentz 
815115f02b91SLuiz Augusto von Dentz 	return 0;
815215f02b91SLuiz Augusto von Dentz }
815315f02b91SLuiz Augusto von Dentz 
81540a708f8fSGustavo F. Padovan /* ---- L2CAP interface with lower layer (HCI) ---- */
81550a708f8fSGustavo F. Padovan 
8156686ebf28SUlisses Furquim int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
81570a708f8fSGustavo F. Padovan {
81580a708f8fSGustavo F. Padovan 	int exact = 0, lm1 = 0, lm2 = 0;
815923691d75SGustavo F. Padovan 	struct l2cap_chan *c;
81600a708f8fSGustavo F. Padovan 
81616ed93dc6SAndrei Emeltchenko 	BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr);
81620a708f8fSGustavo F. Padovan 
81630a708f8fSGustavo F. Padovan 	/* Find listening sockets and check their link_mode */
816423691d75SGustavo F. Padovan 	read_lock(&chan_list_lock);
816523691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
816689bc500eSGustavo F. Padovan 		if (c->state != BT_LISTEN)
81670a708f8fSGustavo F. Padovan 			continue;
81680a708f8fSGustavo F. Padovan 
81697eafc59eSMarcel Holtmann 		if (!bacmp(&c->src, &hdev->bdaddr)) {
81700a708f8fSGustavo F. Padovan 			lm1 |= HCI_LM_ACCEPT;
817143bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
81720a708f8fSGustavo F. Padovan 				lm1 |= HCI_LM_MASTER;
81730a708f8fSGustavo F. Padovan 			exact++;
81747eafc59eSMarcel Holtmann 		} else if (!bacmp(&c->src, BDADDR_ANY)) {
81750a708f8fSGustavo F. Padovan 			lm2 |= HCI_LM_ACCEPT;
817643bd0f32SAndrei Emeltchenko 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
81770a708f8fSGustavo F. Padovan 				lm2 |= HCI_LM_MASTER;
81780a708f8fSGustavo F. Padovan 		}
81790a708f8fSGustavo F. Padovan 	}
818023691d75SGustavo F. Padovan 	read_unlock(&chan_list_lock);
81810a708f8fSGustavo F. Padovan 
81820a708f8fSGustavo F. Padovan 	return exact ? lm1 : lm2;
81830a708f8fSGustavo F. Padovan }
81840a708f8fSGustavo F. Padovan 
8185e760ec12SJohan Hedberg /* Find the next fixed channel in BT_LISTEN state, continue iteration
8186e760ec12SJohan Hedberg  * from an existing channel in the list or from the beginning of the
8187e760ec12SJohan Hedberg  * global list (by passing NULL as first parameter).
8188e760ec12SJohan Hedberg  */
8189e760ec12SJohan Hedberg static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
8190327a7191SJohan Hedberg 						  struct hci_conn *hcon)
8191e760ec12SJohan Hedberg {
8192327a7191SJohan Hedberg 	u8 src_type = bdaddr_src_type(hcon);
8193327a7191SJohan Hedberg 
8194e760ec12SJohan Hedberg 	read_lock(&chan_list_lock);
8195e760ec12SJohan Hedberg 
8196e760ec12SJohan Hedberg 	if (c)
8197e760ec12SJohan Hedberg 		c = list_next_entry(c, global_l);
8198e760ec12SJohan Hedberg 	else
8199e760ec12SJohan Hedberg 		c = list_entry(chan_list.next, typeof(*c), global_l);
8200e760ec12SJohan Hedberg 
8201e760ec12SJohan Hedberg 	list_for_each_entry_from(c, &chan_list, global_l) {
8202e760ec12SJohan Hedberg 		if (c->chan_type != L2CAP_CHAN_FIXED)
8203e760ec12SJohan Hedberg 			continue;
8204e760ec12SJohan Hedberg 		if (c->state != BT_LISTEN)
8205e760ec12SJohan Hedberg 			continue;
8206327a7191SJohan Hedberg 		if (bacmp(&c->src, &hcon->src) && bacmp(&c->src, BDADDR_ANY))
8207e760ec12SJohan Hedberg 			continue;
8208327a7191SJohan Hedberg 		if (src_type != c->src_type)
820954a1b626SJohan Hedberg 			continue;
8210e760ec12SJohan Hedberg 
8211d0be8347SLuiz Augusto von Dentz 		c = l2cap_chan_hold_unless_zero(c);
8212e760ec12SJohan Hedberg 		read_unlock(&chan_list_lock);
8213e760ec12SJohan Hedberg 		return c;
8214e760ec12SJohan Hedberg 	}
8215e760ec12SJohan Hedberg 
8216e760ec12SJohan Hedberg 	read_unlock(&chan_list_lock);
8217e760ec12SJohan Hedberg 
8218e760ec12SJohan Hedberg 	return NULL;
8219e760ec12SJohan Hedberg }
8220e760ec12SJohan Hedberg 
8221539c496dSJohan Hedberg static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
82220a708f8fSGustavo F. Padovan {
8223e760ec12SJohan Hedberg 	struct hci_dev *hdev = hcon->hdev;
82240a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn;
8225e760ec12SJohan Hedberg 	struct l2cap_chan *pchan;
8226e760ec12SJohan Hedberg 	u8 dst_type;
82270a708f8fSGustavo F. Padovan 
8228539c496dSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
8229539c496dSJohan Hedberg 		return;
8230539c496dSJohan Hedberg 
82316ed93dc6SAndrei Emeltchenko 	BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
82320a708f8fSGustavo F. Padovan 
8233dc0f5088SJohan Hedberg 	if (status) {
8234e175072fSJoe Perches 		l2cap_conn_del(hcon, bt_to_errno(status));
8235dc0f5088SJohan Hedberg 		return;
8236ba6fc317SAndrei Emeltchenko 	}
8237dc0f5088SJohan Hedberg 
8238dc0f5088SJohan Hedberg 	conn = l2cap_conn_add(hcon);
8239dc0f5088SJohan Hedberg 	if (!conn)
8240dc0f5088SJohan Hedberg 		return;
8241dc0f5088SJohan Hedberg 
8242a250e048SJohan Hedberg 	dst_type = bdaddr_dst_type(hcon);
8243e760ec12SJohan Hedberg 
8244e760ec12SJohan Hedberg 	/* If device is blocked, do not create channels for it */
82453d4f9c00SArchie Pusaka 	if (hci_bdaddr_list_lookup(&hdev->reject_list, &hcon->dst, dst_type))
8246e760ec12SJohan Hedberg 		return;
8247e760ec12SJohan Hedberg 
8248e760ec12SJohan Hedberg 	/* Find fixed channels and notify them of the new connection. We
8249e760ec12SJohan Hedberg 	 * use multiple individual lookups, continuing each time where
8250e760ec12SJohan Hedberg 	 * we left off, because the list lock would prevent calling the
8251e760ec12SJohan Hedberg 	 * potentially sleeping l2cap_chan_lock() function.
8252e760ec12SJohan Hedberg 	 */
8253327a7191SJohan Hedberg 	pchan = l2cap_global_fixed_chan(NULL, hcon);
8254e760ec12SJohan Hedberg 	while (pchan) {
8255e760ec12SJohan Hedberg 		struct l2cap_chan *chan, *next;
8256e760ec12SJohan Hedberg 
8257e760ec12SJohan Hedberg 		/* Client fixed channels should override server ones */
8258e760ec12SJohan Hedberg 		if (__l2cap_get_chan_by_dcid(conn, pchan->scid))
8259e760ec12SJohan Hedberg 			goto next;
8260e760ec12SJohan Hedberg 
8261e760ec12SJohan Hedberg 		l2cap_chan_lock(pchan);
8262e760ec12SJohan Hedberg 		chan = pchan->ops->new_connection(pchan);
8263e760ec12SJohan Hedberg 		if (chan) {
8264e760ec12SJohan Hedberg 			bacpy(&chan->src, &hcon->src);
8265e760ec12SJohan Hedberg 			bacpy(&chan->dst, &hcon->dst);
8266a250e048SJohan Hedberg 			chan->src_type = bdaddr_src_type(hcon);
8267e760ec12SJohan Hedberg 			chan->dst_type = dst_type;
8268e760ec12SJohan Hedberg 
8269e760ec12SJohan Hedberg 			__l2cap_chan_add(conn, chan);
8270e760ec12SJohan Hedberg 		}
8271e760ec12SJohan Hedberg 
8272e760ec12SJohan Hedberg 		l2cap_chan_unlock(pchan);
8273e760ec12SJohan Hedberg next:
8274327a7191SJohan Hedberg 		next = l2cap_global_fixed_chan(pchan, hcon);
8275e760ec12SJohan Hedberg 		l2cap_chan_put(pchan);
8276e760ec12SJohan Hedberg 		pchan = next;
8277e760ec12SJohan Hedberg 	}
8278e760ec12SJohan Hedberg 
8279dc0f5088SJohan Hedberg 	l2cap_conn_ready(conn);
82800a708f8fSGustavo F. Padovan }
82810a708f8fSGustavo F. Padovan 
8282686ebf28SUlisses Furquim int l2cap_disconn_ind(struct hci_conn *hcon)
82830a708f8fSGustavo F. Padovan {
82840a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
82850a708f8fSGustavo F. Padovan 
82860a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p", hcon);
82870a708f8fSGustavo F. Padovan 
8288686ebf28SUlisses Furquim 	if (!conn)
82899f5a0d7bSAndrei Emeltchenko 		return HCI_ERROR_REMOTE_USER_TERM;
82900a708f8fSGustavo F. Padovan 	return conn->disc_reason;
82910a708f8fSGustavo F. Padovan }
82920a708f8fSGustavo F. Padovan 
82933a6d576bSJohan Hedberg static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
82940a708f8fSGustavo F. Padovan {
82953a6d576bSJohan Hedberg 	if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
82963a6d576bSJohan Hedberg 		return;
82973a6d576bSJohan Hedberg 
82980a708f8fSGustavo F. Padovan 	BT_DBG("hcon %p reason %d", hcon, reason);
82990a708f8fSGustavo F. Padovan 
8300e175072fSJoe Perches 	l2cap_conn_del(hcon, bt_to_errno(reason));
83010a708f8fSGustavo F. Padovan }
83020a708f8fSGustavo F. Padovan 
83034343478fSGustavo F. Padovan static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
83040a708f8fSGustavo F. Padovan {
8305715ec005SGustavo F. Padovan 	if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
83060a708f8fSGustavo F. Padovan 		return;
83070a708f8fSGustavo F. Padovan 
83080a708f8fSGustavo F. Padovan 	if (encrypt == 0x00) {
83094343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM) {
8310ba13ccd9SMarcel Holtmann 			__set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
83117d513e92SMarcel Holtmann 		} else if (chan->sec_level == BT_SECURITY_HIGH ||
83127d513e92SMarcel Holtmann 			   chan->sec_level == BT_SECURITY_FIPS)
83130f852724SGustavo F. Padovan 			l2cap_chan_close(chan, ECONNREFUSED);
83140a708f8fSGustavo F. Padovan 	} else {
83154343478fSGustavo F. Padovan 		if (chan->sec_level == BT_SECURITY_MEDIUM)
8316c9b66675SGustavo F. Padovan 			__clear_chan_timer(chan);
83170a708f8fSGustavo F. Padovan 	}
83180a708f8fSGustavo F. Padovan }
83190a708f8fSGustavo F. Padovan 
8320354fe804SJohan Hedberg static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
83210a708f8fSGustavo F. Padovan {
83220a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
832348454079SGustavo F. Padovan 	struct l2cap_chan *chan;
83240a708f8fSGustavo F. Padovan 
83250a708f8fSGustavo F. Padovan 	if (!conn)
8326354fe804SJohan Hedberg 		return;
83270a708f8fSGustavo F. Padovan 
832889d8b407SAndrei Emeltchenko 	BT_DBG("conn %p status 0x%2.2x encrypt %u", conn, status, encrypt);
83290a708f8fSGustavo F. Padovan 
83303df91ea2SAndrei Emeltchenko 	mutex_lock(&conn->chan_lock);
83310a708f8fSGustavo F. Padovan 
83323df91ea2SAndrei Emeltchenko 	list_for_each_entry(chan, &conn->chan_l, list) {
83336be36555SAndrei Emeltchenko 		l2cap_chan_lock(chan);
83340a708f8fSGustavo F. Padovan 
833589d8b407SAndrei Emeltchenko 		BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
833689d8b407SAndrei Emeltchenko 		       state_to_string(chan->state));
8337f1cb9af5SVinicius Costa Gomes 
83382338a7e0SJohan Hedberg 		if (chan->scid == L2CAP_CID_A2MP) {
833978eb2f98SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
834078eb2f98SAndrei Emeltchenko 			continue;
834178eb2f98SAndrei Emeltchenko 		}
834278eb2f98SAndrei Emeltchenko 
8343191eb398SJohan Hedberg 		if (!status && encrypt)
8344f1cb9af5SVinicius Costa Gomes 			chan->sec_level = hcon->sec_level;
8345f1cb9af5SVinicius Costa Gomes 
834696eff46eSAndrei Emeltchenko 		if (!__l2cap_no_conn_pending(chan)) {
83476be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
83480a708f8fSGustavo F. Padovan 			continue;
83490a708f8fSGustavo F. Padovan 		}
83500a708f8fSGustavo F. Padovan 
835189bc500eSGustavo F. Padovan 		if (!status && (chan->state == BT_CONNECTED ||
835289bc500eSGustavo F. Padovan 				chan->state == BT_CONFIG)) {
8353d97c899bSMarcel Holtmann 			chan->ops->resume(chan);
83544343478fSGustavo F. Padovan 			l2cap_check_encryption(chan, encrypt);
83556be36555SAndrei Emeltchenko 			l2cap_chan_unlock(chan);
83560a708f8fSGustavo F. Padovan 			continue;
83570a708f8fSGustavo F. Padovan 		}
83580a708f8fSGustavo F. Padovan 
835989bc500eSGustavo F. Padovan 		if (chan->state == BT_CONNECT) {
8360693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon))
836193c3e8f5SAndrei Emeltchenko 				l2cap_start_connection(chan);
83626d3c15daSJohan Hedberg 			else
8363ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8364fa37c1aaSJohan Hedberg 		} else if (chan->state == BT_CONNECT2 &&
836515f02b91SLuiz Augusto von Dentz 			   !(chan->mode == L2CAP_MODE_EXT_FLOWCTL ||
836615f02b91SLuiz Augusto von Dentz 			     chan->mode == L2CAP_MODE_LE_FLOWCTL)) {
83670a708f8fSGustavo F. Padovan 			struct l2cap_conn_rsp rsp;
8368df3c3931SJohan Hedberg 			__u16 res, stat;
83690a708f8fSGustavo F. Padovan 
8370693cd8ceSMarcel Holtmann 			if (!status && l2cap_check_enc_key_size(hcon)) {
8371bdc25783SMarcel Holtmann 				if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
8372df3c3931SJohan Hedberg 					res = L2CAP_CR_PEND;
8373df3c3931SJohan Hedberg 					stat = L2CAP_CS_AUTHOR_PEND;
83742dc4e510SGustavo Padovan 					chan->ops->defer(chan);
8375df3c3931SJohan Hedberg 				} else {
8376acdcabf5SGustavo Padovan 					l2cap_state_change(chan, BT_CONFIG);
8377df3c3931SJohan Hedberg 					res = L2CAP_CR_SUCCESS;
8378df3c3931SJohan Hedberg 					stat = L2CAP_CS_NO_INFO;
8379df3c3931SJohan Hedberg 				}
83800a708f8fSGustavo F. Padovan 			} else {
8381acdcabf5SGustavo Padovan 				l2cap_state_change(chan, BT_DISCONN);
8382ba13ccd9SMarcel Holtmann 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
8383df3c3931SJohan Hedberg 				res = L2CAP_CR_SEC_BLOCK;
8384df3c3931SJohan Hedberg 				stat = L2CAP_CS_NO_INFO;
83850a708f8fSGustavo F. Padovan 			}
83860a708f8fSGustavo F. Padovan 
8387fe4128e0SGustavo F. Padovan 			rsp.scid   = cpu_to_le16(chan->dcid);
8388fe4128e0SGustavo F. Padovan 			rsp.dcid   = cpu_to_le16(chan->scid);
8389df3c3931SJohan Hedberg 			rsp.result = cpu_to_le16(res);
8390df3c3931SJohan Hedberg 			rsp.status = cpu_to_le16(stat);
8391fc7f8a7eSGustavo F. Padovan 			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
8392fc7f8a7eSGustavo F. Padovan 				       sizeof(rsp), &rsp);
83932d369359SMat Martineau 
83942d369359SMat Martineau 			if (!test_bit(CONF_REQ_SENT, &chan->conf_state) &&
83952d369359SMat Martineau 			    res == L2CAP_CR_SUCCESS) {
83962d369359SMat Martineau 				char buf[128];
83972d369359SMat Martineau 				set_bit(CONF_REQ_SENT, &chan->conf_state);
83982d369359SMat Martineau 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
83992d369359SMat Martineau 					       L2CAP_CONF_REQ,
8400e860d2c9SBen Seri 					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
84012d369359SMat Martineau 					       buf);
84022d369359SMat Martineau 				chan->num_conf_req++;
84032d369359SMat Martineau 			}
84040a708f8fSGustavo F. Padovan 		}
84050a708f8fSGustavo F. Padovan 
84066be36555SAndrei Emeltchenko 		l2cap_chan_unlock(chan);
84070a708f8fSGustavo F. Padovan 	}
84080a708f8fSGustavo F. Padovan 
84093df91ea2SAndrei Emeltchenko 	mutex_unlock(&conn->chan_lock);
84100a708f8fSGustavo F. Padovan }
84110a708f8fSGustavo F. Padovan 
84124d7ea8eeSLuiz Augusto von Dentz /* Append fragment into frame respecting the maximum len of rx_skb */
84134d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb,
84144d7ea8eeSLuiz Augusto von Dentz 			   u16 len)
84154d7ea8eeSLuiz Augusto von Dentz {
84164d7ea8eeSLuiz Augusto von Dentz 	if (!conn->rx_skb) {
84174d7ea8eeSLuiz Augusto von Dentz 		/* Allocate skb for the complete frame (with header) */
84184d7ea8eeSLuiz Augusto von Dentz 		conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL);
84194d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb)
84204d7ea8eeSLuiz Augusto von Dentz 			return -ENOMEM;
84214d7ea8eeSLuiz Augusto von Dentz 		/* Init rx_len */
84224d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len;
84234d7ea8eeSLuiz Augusto von Dentz 	}
84244d7ea8eeSLuiz Augusto von Dentz 
84254d7ea8eeSLuiz Augusto von Dentz 	/* Copy as much as the rx_skb can hold */
84264d7ea8eeSLuiz Augusto von Dentz 	len = min_t(u16, len, skb->len);
84274d7ea8eeSLuiz Augusto von Dentz 	skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, len), len);
84284d7ea8eeSLuiz Augusto von Dentz 	skb_pull(skb, len);
84294d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len -= len;
84304d7ea8eeSLuiz Augusto von Dentz 
84314d7ea8eeSLuiz Augusto von Dentz 	return len;
84324d7ea8eeSLuiz Augusto von Dentz }
84334d7ea8eeSLuiz Augusto von Dentz 
84344d7ea8eeSLuiz Augusto von Dentz static int l2cap_recv_len(struct l2cap_conn *conn, struct sk_buff *skb)
84354d7ea8eeSLuiz Augusto von Dentz {
84364d7ea8eeSLuiz Augusto von Dentz 	struct sk_buff *rx_skb;
84374d7ea8eeSLuiz Augusto von Dentz 	int len;
84384d7ea8eeSLuiz Augusto von Dentz 
84394d7ea8eeSLuiz Augusto von Dentz 	/* Append just enough to complete the header */
84404d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, skb, L2CAP_LEN_SIZE - conn->rx_skb->len);
84414d7ea8eeSLuiz Augusto von Dentz 
84424d7ea8eeSLuiz Augusto von Dentz 	/* If header could not be read just continue */
84434d7ea8eeSLuiz Augusto von Dentz 	if (len < 0 || conn->rx_skb->len < L2CAP_LEN_SIZE)
84444d7ea8eeSLuiz Augusto von Dentz 		return len;
84454d7ea8eeSLuiz Augusto von Dentz 
84464d7ea8eeSLuiz Augusto von Dentz 	rx_skb = conn->rx_skb;
84474d7ea8eeSLuiz Augusto von Dentz 	len = get_unaligned_le16(rx_skb->data);
84484d7ea8eeSLuiz Augusto von Dentz 
84494d7ea8eeSLuiz Augusto von Dentz 	/* Check if rx_skb has enough space to received all fragments */
84504d7ea8eeSLuiz Augusto von Dentz 	if (len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE) <= skb_tailroom(rx_skb)) {
84514d7ea8eeSLuiz Augusto von Dentz 		/* Update expected len */
84524d7ea8eeSLuiz Augusto von Dentz 		conn->rx_len = len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE);
84534d7ea8eeSLuiz Augusto von Dentz 		return L2CAP_LEN_SIZE;
84544d7ea8eeSLuiz Augusto von Dentz 	}
84554d7ea8eeSLuiz Augusto von Dentz 
84564d7ea8eeSLuiz Augusto von Dentz 	/* Reset conn->rx_skb since it will need to be reallocated in order to
84574d7ea8eeSLuiz Augusto von Dentz 	 * fit all fragments.
84584d7ea8eeSLuiz Augusto von Dentz 	 */
84594d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
84604d7ea8eeSLuiz Augusto von Dentz 
84614d7ea8eeSLuiz Augusto von Dentz 	/* Reallocates rx_skb using the exact expected length */
84624d7ea8eeSLuiz Augusto von Dentz 	len = l2cap_recv_frag(conn, rx_skb,
84634d7ea8eeSLuiz Augusto von Dentz 			      len + (L2CAP_HDR_SIZE - L2CAP_LEN_SIZE));
84644d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(rx_skb);
84654d7ea8eeSLuiz Augusto von Dentz 
84664d7ea8eeSLuiz Augusto von Dentz 	return len;
84674d7ea8eeSLuiz Augusto von Dentz }
84684d7ea8eeSLuiz Augusto von Dentz 
84694d7ea8eeSLuiz Augusto von Dentz static void l2cap_recv_reset(struct l2cap_conn *conn)
84704d7ea8eeSLuiz Augusto von Dentz {
84714d7ea8eeSLuiz Augusto von Dentz 	kfree_skb(conn->rx_skb);
84724d7ea8eeSLuiz Augusto von Dentz 	conn->rx_skb = NULL;
84734d7ea8eeSLuiz Augusto von Dentz 	conn->rx_len = 0;
84744d7ea8eeSLuiz Augusto von Dentz }
84754d7ea8eeSLuiz Augusto von Dentz 
84769b4c3336SArron Wang void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
84770a708f8fSGustavo F. Padovan {
84780a708f8fSGustavo F. Padovan 	struct l2cap_conn *conn = hcon->l2cap_data;
8479d73a0988SAndrei Emeltchenko 	int len;
84800a708f8fSGustavo F. Padovan 
84811d13a254SAndrei Emeltchenko 	/* For AMP controller do not create l2cap conn */
8482ca8bee5dSMarcel Holtmann 	if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
84831d13a254SAndrei Emeltchenko 		goto drop;
84840a708f8fSGustavo F. Padovan 
84850a708f8fSGustavo F. Padovan 	if (!conn)
8486baf43251SClaudio Takahasi 		conn = l2cap_conn_add(hcon);
84870a708f8fSGustavo F. Padovan 
84880a708f8fSGustavo F. Padovan 	if (!conn)
84890a708f8fSGustavo F. Padovan 		goto drop;
84900a708f8fSGustavo F. Padovan 
849193917fd2SKai Ye 	BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags);
84920a708f8fSGustavo F. Padovan 
8493d73a0988SAndrei Emeltchenko 	switch (flags) {
8494d73a0988SAndrei Emeltchenko 	case ACL_START:
8495d73a0988SAndrei Emeltchenko 	case ACL_START_NO_FLUSH:
8496d73a0988SAndrei Emeltchenko 	case ACL_COMPLETE:
84974d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb) {
84980a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected start frame (len %d)", skb->len);
84994d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
85000a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
85010a708f8fSGustavo F. Padovan 		}
85020a708f8fSGustavo F. Padovan 
85034d7ea8eeSLuiz Augusto von Dentz 		/* Start fragment may not contain the L2CAP length so just
85044d7ea8eeSLuiz Augusto von Dentz 		 * copy the initial byte when that happens and use conn->mtu as
85054d7ea8eeSLuiz Augusto von Dentz 		 * expected length.
85064d7ea8eeSLuiz Augusto von Dentz 		 */
85074d7ea8eeSLuiz Augusto von Dentz 		if (skb->len < L2CAP_LEN_SIZE) {
85087c9524d9SHawkins Jiawei 			l2cap_recv_frag(conn, skb, conn->mtu);
85097c9524d9SHawkins Jiawei 			break;
85100a708f8fSGustavo F. Padovan 		}
85110a708f8fSGustavo F. Padovan 
85124d7ea8eeSLuiz Augusto von Dentz 		len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
85130a708f8fSGustavo F. Padovan 
85140a708f8fSGustavo F. Padovan 		if (len == skb->len) {
85150a708f8fSGustavo F. Padovan 			/* Complete frame received */
85160a708f8fSGustavo F. Padovan 			l2cap_recv_frame(conn, skb);
85179b4c3336SArron Wang 			return;
85180a708f8fSGustavo F. Padovan 		}
85190a708f8fSGustavo F. Padovan 
852093917fd2SKai Ye 		BT_DBG("Start: total len %d, frag len %u", len, skb->len);
85210a708f8fSGustavo F. Padovan 
85220a708f8fSGustavo F. Padovan 		if (skb->len > len) {
852393917fd2SKai Ye 			BT_ERR("Frame is too long (len %u, expected len %d)",
85240a708f8fSGustavo F. Padovan 			       skb->len, len);
85250a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
85260a708f8fSGustavo F. Padovan 			goto drop;
85270a708f8fSGustavo F. Padovan 		}
85280a708f8fSGustavo F. Padovan 
85294d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
85304d7ea8eeSLuiz Augusto von Dentz 		if (l2cap_recv_frag(conn, skb, len) < 0)
85310a708f8fSGustavo F. Padovan 			goto drop;
85320a708f8fSGustavo F. Padovan 
8533d73a0988SAndrei Emeltchenko 		break;
8534d73a0988SAndrei Emeltchenko 
8535d73a0988SAndrei Emeltchenko 	case ACL_CONT:
853693917fd2SKai Ye 		BT_DBG("Cont: frag len %u (expecting %u)", skb->len, conn->rx_len);
85370a708f8fSGustavo F. Padovan 
85384d7ea8eeSLuiz Augusto von Dentz 		if (!conn->rx_skb) {
85390a708f8fSGustavo F. Padovan 			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
85400a708f8fSGustavo F. Padovan 			l2cap_conn_unreliable(conn, ECOMM);
85410a708f8fSGustavo F. Padovan 			goto drop;
85420a708f8fSGustavo F. Padovan 		}
85430a708f8fSGustavo F. Padovan 
85444d7ea8eeSLuiz Augusto von Dentz 		/* Complete the L2CAP length if it has not been read */
85454d7ea8eeSLuiz Augusto von Dentz 		if (conn->rx_skb->len < L2CAP_LEN_SIZE) {
85464d7ea8eeSLuiz Augusto von Dentz 			if (l2cap_recv_len(conn, skb) < 0) {
85470a708f8fSGustavo F. Padovan 				l2cap_conn_unreliable(conn, ECOMM);
85480a708f8fSGustavo F. Padovan 				goto drop;
85490a708f8fSGustavo F. Padovan 			}
85500a708f8fSGustavo F. Padovan 
85514d7ea8eeSLuiz Augusto von Dentz 			/* Header still could not be read just continue */
85524d7ea8eeSLuiz Augusto von Dentz 			if (conn->rx_skb->len < L2CAP_LEN_SIZE)
85537c9524d9SHawkins Jiawei 				break;
85544d7ea8eeSLuiz Augusto von Dentz 		}
85554d7ea8eeSLuiz Augusto von Dentz 
85564d7ea8eeSLuiz Augusto von Dentz 		if (skb->len > conn->rx_len) {
855793917fd2SKai Ye 			BT_ERR("Fragment is too long (len %u, expected %u)",
85584d7ea8eeSLuiz Augusto von Dentz 			       skb->len, conn->rx_len);
85594d7ea8eeSLuiz Augusto von Dentz 			l2cap_recv_reset(conn);
85604d7ea8eeSLuiz Augusto von Dentz 			l2cap_conn_unreliable(conn, ECOMM);
85614d7ea8eeSLuiz Augusto von Dentz 			goto drop;
85624d7ea8eeSLuiz Augusto von Dentz 		}
85634d7ea8eeSLuiz Augusto von Dentz 
85644d7ea8eeSLuiz Augusto von Dentz 		/* Append fragment into frame (with header) */
85654d7ea8eeSLuiz Augusto von Dentz 		l2cap_recv_frag(conn, skb, skb->len);
85660a708f8fSGustavo F. Padovan 
85670a708f8fSGustavo F. Padovan 		if (!conn->rx_len) {
8568c4e5bafaSJohan Hedberg 			/* Complete frame received. l2cap_recv_frame
8569c4e5bafaSJohan Hedberg 			 * takes ownership of the skb so set the global
8570c4e5bafaSJohan Hedberg 			 * rx_skb pointer to NULL first.
8571c4e5bafaSJohan Hedberg 			 */
8572c4e5bafaSJohan Hedberg 			struct sk_buff *rx_skb = conn->rx_skb;
85730a708f8fSGustavo F. Padovan 			conn->rx_skb = NULL;
8574c4e5bafaSJohan Hedberg 			l2cap_recv_frame(conn, rx_skb);
85750a708f8fSGustavo F. Padovan 		}
8576d73a0988SAndrei Emeltchenko 		break;
85770a708f8fSGustavo F. Padovan 	}
85780a708f8fSGustavo F. Padovan 
85790a708f8fSGustavo F. Padovan drop:
85800a708f8fSGustavo F. Padovan 	kfree_skb(skb);
85810a708f8fSGustavo F. Padovan }
85820a708f8fSGustavo F. Padovan 
8583354fe804SJohan Hedberg static struct hci_cb l2cap_cb = {
8584354fe804SJohan Hedberg 	.name		= "L2CAP",
8585539c496dSJohan Hedberg 	.connect_cfm	= l2cap_connect_cfm,
85863a6d576bSJohan Hedberg 	.disconn_cfm	= l2cap_disconn_cfm,
8587354fe804SJohan Hedberg 	.security_cfm	= l2cap_security_cfm,
8588354fe804SJohan Hedberg };
8589354fe804SJohan Hedberg 
85900a708f8fSGustavo F. Padovan static int l2cap_debugfs_show(struct seq_file *f, void *p)
85910a708f8fSGustavo F. Padovan {
859223691d75SGustavo F. Padovan 	struct l2cap_chan *c;
85930a708f8fSGustavo F. Padovan 
8594333055f2SGustavo F. Padovan 	read_lock(&chan_list_lock);
85950a708f8fSGustavo F. Padovan 
859623691d75SGustavo F. Padovan 	list_for_each_entry(c, &chan_list, global_l) {
8597eeb5a067SMarcel Holtmann 		seq_printf(f, "%pMR (%u) %pMR (%u) %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
8598eeb5a067SMarcel Holtmann 			   &c->src, c->src_type, &c->dst, c->dst_type,
859989bc500eSGustavo F. Padovan 			   c->state, __le16_to_cpu(c->psm),
860023691d75SGustavo F. Padovan 			   c->scid, c->dcid, c->imtu, c->omtu,
860123691d75SGustavo F. Padovan 			   c->sec_level, c->mode);
86020a708f8fSGustavo F. Padovan 	}
86030a708f8fSGustavo F. Padovan 
8604333055f2SGustavo F. Padovan 	read_unlock(&chan_list_lock);
86050a708f8fSGustavo F. Padovan 
86060a708f8fSGustavo F. Padovan 	return 0;
86070a708f8fSGustavo F. Padovan }
86080a708f8fSGustavo F. Padovan 
86098e2924e3SYangtao Li DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
86100a708f8fSGustavo F. Padovan 
86110a708f8fSGustavo F. Padovan static struct dentry *l2cap_debugfs;
86120a708f8fSGustavo F. Padovan 
861364274518SGustavo F. Padovan int __init l2cap_init(void)
86140a708f8fSGustavo F. Padovan {
86150a708f8fSGustavo F. Padovan 	int err;
86160a708f8fSGustavo F. Padovan 
8617bb58f747SGustavo F. Padovan 	err = l2cap_init_sockets();
86180a708f8fSGustavo F. Padovan 	if (err < 0)
86190a708f8fSGustavo F. Padovan 		return err;
86200a708f8fSGustavo F. Padovan 
8621354fe804SJohan Hedberg 	hci_register_cb(&l2cap_cb);
8622354fe804SJohan Hedberg 
86231120e4bfSMarcel Holtmann 	if (IS_ERR_OR_NULL(bt_debugfs))
86241120e4bfSMarcel Holtmann 		return 0;
86251120e4bfSMarcel Holtmann 
86262d792818SGustavo Padovan 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
86272d792818SGustavo Padovan 					    NULL, &l2cap_debugfs_fops);
86280a708f8fSGustavo F. Padovan 
86290a708f8fSGustavo F. Padovan 	return 0;
86300a708f8fSGustavo F. Padovan }
86310a708f8fSGustavo F. Padovan 
863264274518SGustavo F. Padovan void l2cap_exit(void)
86330a708f8fSGustavo F. Padovan {
86340a708f8fSGustavo F. Padovan 	debugfs_remove(l2cap_debugfs);
8635354fe804SJohan Hedberg 	hci_unregister_cb(&l2cap_cb);
8636bb58f747SGustavo F. Padovan 	l2cap_cleanup_sockets();
86370a708f8fSGustavo F. Padovan }
86380a708f8fSGustavo F. Padovan 
86390a708f8fSGustavo F. Padovan module_param(disable_ertm, bool, 0644);
86400a708f8fSGustavo F. Padovan MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
86414be5ca67SLuiz Augusto von Dentz 
86424be5ca67SLuiz Augusto von Dentz module_param(enable_ecred, bool, 0644);
86434be5ca67SLuiz Augusto von Dentz MODULE_PARM_DESC(enable_ecred, "Enable enhanced credit flow control mode");
8644