All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 00/16] EWS: extended window size and extended control field support
@ 2011-10-11 10:37 Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 01/16] Bluetooth: clean up spaces in L2CAP header Emeltchenko Andrei
                   ` (15 more replies)
  0 siblings, 16 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds support for extended window size option (EWS) and extended control
field. Code partly based on Atheros patches sent a year ago by Haijun Liu
http://marc.info/?a=128277503500005&r=1&w=2
and Qualcomm code git://codeaurora.org/kernel/msm.git.

To decode EWS option and extended control field please apply patch to hcidump
which I sent to linux-bluetooth.

Changes:
	* RFCv1: rebase and using l2cap_chan flag for ext control
	* PATCHv1: small fix for tx_seq u8->u16
	* PATCHv2: use enable_hs instead of disable_extwindow,
		code style fixes, fix pdu calculation and remove magic
		numbers.
	* PATCHv3: major rebase and split to smaller logical chunks, taking
		comments from upstream.

Andrei Emeltchenko (16):
  Bluetooth: clean up spaces in L2CAP header
  Bluetooth: EWS: extended window size option support
  Bluetooth: EWS: adds ext control field bit mask
  Bluetooth: EWS: rewrite handling Supervisory (S) bits
  Bluetooth: EWS: rewrite handling SAR bits
  Bluetooth: EWS: rewrite reqseq calculation
  Bluetooth: EWS: rewrite L2CAP ERTM txseq calculation
  Bluetooth: EWS: rewrite check frame type function
  Bluetooth: EWS: rewrite handling FINAL (F) bit
  Bluetooth: EWS: rewrite handling POLL (P) bit
  Bluetooth: EWS: handling different Control fields
  Bluetooth: EWS: recalculate L2CAP header size
  Bluetooth: EWS: support extended seq numbers
  Bluetooth: EWS: define L2CAP header sizes
  Bluetooth: EWS: remove magic numbers in l2cap
  Bluetooth: EWS: fix max_pdu calculation

 include/net/bluetooth/bluetooth.h |    2 +-
 include/net/bluetooth/l2cap.h     |  301 ++++++++++++++++++++----
 net/bluetooth/l2cap_core.c        |  478 ++++++++++++++++++++++---------------
 net/bluetooth/l2cap_sock.c        |    8 +-
 4 files changed, 543 insertions(+), 246 deletions(-)

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCHv3 01/16] Bluetooth: clean up spaces in L2CAP header
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 02/16] Bluetooth: EWS: extended window size option support Emeltchenko Andrei
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Spaces converted to tabs

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index aea083c..08ad40b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -134,10 +134,9 @@ struct l2cap_conninfo {
 #define L2CAP_SDU_CONTINUE          0xC000
 
 /* L2CAP Command rej. reasons */
-#define L2CAP_REJ_NOT_UNDERSTOOD      0x0000
-#define L2CAP_REJ_MTU_EXCEEDED        0x0001
-#define L2CAP_REJ_INVALID_CID         0x0002
-
+#define L2CAP_REJ_NOT_UNDERSTOOD	0x0000
+#define L2CAP_REJ_MTU_EXCEEDED		0x0001
+#define L2CAP_REJ_INVALID_CID		0x0002
 
 /* L2CAP structures */
 struct l2cap_hdr {
@@ -273,13 +272,13 @@ struct l2cap_info_rsp {
 } __packed;
 
 /* info type */
-#define L2CAP_IT_CL_MTU     0x0001
-#define L2CAP_IT_FEAT_MASK  0x0002
-#define L2CAP_IT_FIXED_CHAN 0x0003
+#define L2CAP_IT_CL_MTU		0x0001
+#define L2CAP_IT_FEAT_MASK	0x0002
+#define L2CAP_IT_FIXED_CHAN	0x0003
 
 /* info result */
-#define L2CAP_IR_SUCCESS    0x0000
-#define L2CAP_IR_NOTSUPP    0x0001
+#define L2CAP_IR_SUCCESS	0x0000
+#define L2CAP_IR_NOTSUPP	0x0001
 
 struct l2cap_conn_param_update_req {
 	__le16      min;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 02/16] Bluetooth: EWS: extended window size option support
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 01/16] Bluetooth: clean up spaces in L2CAP header Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 03/16] Bluetooth: EWS: adds ext control field bit mask Emeltchenko Andrei
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds support for extended window size (EWS) config option. We enable EWS
feature in L2CAP Info RSP when hs enabled. EWS option is included in L2CAP
Config Req if tx_win (which is set via socket) bigger then standard default
value (63) && hs enabled && remote side supports EWS feature.

Using EWS selects extended control field in L2CAP.

Code partly based on Qualcomm and Atheros patches sent upstream a year ago.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |    8 +++++-
 net/bluetooth/l2cap_core.c    |   51 ++++++++++++++++++++++++++++++++++++++--
 net/bluetooth/l2cap_sock.c    |    8 +++---
 3 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 08ad40b..51998ff 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -32,6 +32,7 @@
 #define L2CAP_DEFAULT_MIN_MTU		48
 #define L2CAP_DEFAULT_FLUSH_TO		0xffff
 #define L2CAP_DEFAULT_TX_WINDOW		63
+#define L2CAP_DEFAULT_EXT_WINDOW	0x3FFF
 #define L2CAP_DEFAULT_MAX_TX		3
 #define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
@@ -233,6 +234,7 @@ struct l2cap_conf_opt {
 #define L2CAP_CONF_QOS		0x03
 #define L2CAP_CONF_RFC		0x04
 #define L2CAP_CONF_FCS		0x05
+#define L2CAP_CONF_EWS		0x07
 
 #define L2CAP_CONF_MAX_SIZE	22
 
@@ -333,7 +335,7 @@ struct l2cap_chan {
 
 	__u8		fcs;
 
-	__u8		tx_win;
+	__u16		tx_win;
 	__u8		max_tx;
 	__u16		retrans_timeout;
 	__u16		monitor_timeout;
@@ -357,7 +359,7 @@ struct l2cap_chan {
 	struct sk_buff	*sdu;
 	struct sk_buff	*sdu_last_frag;
 
-	__u8		remote_tx_win;
+	__u16		remote_tx_win;
 	__u8		remote_max_tx;
 	__u16		remote_mps;
 
@@ -442,6 +444,7 @@ enum {
 	CONF_CONNECT_PEND,
 	CONF_NO_FCS_RECV,
 	CONF_STATE2_DEVICE,
+	CONF_EWS_RECV,
 };
 
 #define L2CAP_CONF_MAX_CONF_REQ 2
@@ -465,6 +468,7 @@ enum {
 	FLAG_FORCE_ACTIVE,
 	FLAG_FORCE_RELIABLE,
 	FLAG_FLUSHABLE,
+	FLAG_EXT_CTRL,
 };
 
 #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 18a08c5..6e34312 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1898,6 +1898,22 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
 	}
 }
 
+static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
+{
+	return enable_hs && chan->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
+}
+
+static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
+{
+	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
+						__l2cap_ews_supported(chan))
+		/* use extended control field */
+		set_bit(FLAG_EXT_CTRL, &chan->flags);
+	else
+		chan->tx_win = min_t(u16, chan->tx_win,
+						L2CAP_DEFAULT_TX_WINDOW);
+}
+
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
 {
 	struct l2cap_conf_req *req = data;
@@ -1944,7 +1960,6 @@ done:
 
 	case L2CAP_MODE_ERTM:
 		rfc.mode            = L2CAP_MODE_ERTM;
-		rfc.txwin_size      = chan->tx_win;
 		rfc.max_transmit    = chan->max_tx;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
@@ -1952,6 +1967,11 @@ done:
 		if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
 			rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
 
+		l2cap_txwin_setup(chan);
+
+		rfc.txwin_size = min_t(u16, chan->tx_win,
+						L2CAP_DEFAULT_TX_WINDOW);
+
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
 							(unsigned long) &rfc);
 
@@ -1963,6 +1983,10 @@ done:
 			chan->fcs = L2CAP_FCS_NONE;
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
 		}
+
+		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
+								chan->tx_win);
 		break;
 
 	case L2CAP_MODE_STREAMING:
@@ -2038,6 +2062,15 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 
 			break;
 
+		case L2CAP_CONF_EWS:
+			if (!enable_hs)
+				return -ECONNREFUSED;
+
+			set_bit(FLAG_EXT_CTRL, &chan->flags);
+			set_bit(CONF_EWS_RECV, &chan->conf_state);
+			chan->remote_tx_win = val;
+			break;
+
 		default:
 			if (hint)
 				break;
@@ -2098,7 +2131,11 @@ done:
 			break;
 
 		case L2CAP_MODE_ERTM:
-			chan->remote_tx_win = rfc.txwin_size;
+			if (!test_bit(CONF_EWS_RECV, &chan->conf_state))
+				chan->remote_tx_win = rfc.txwin_size;
+			else
+				rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW;
+
 			chan->remote_max_tx = rfc.max_transmit;
 
 			if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
@@ -2190,6 +2227,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
 			break;
+
+		case L2CAP_CONF_EWS:
+			chan->tx_win = min_t(u16, val,
+						L2CAP_DEFAULT_EXT_WINDOW);
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS,
+							2, chan->tx_win);
+			break;
 		}
 	}
 
@@ -2785,7 +2829,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
 			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
 							 | L2CAP_FEAT_FCS;
 		if (enable_hs)
-			feat_mask |= L2CAP_FEAT_EXT_FLOW;
+			feat_mask |= L2CAP_FEAT_EXT_FLOW
+						| L2CAP_FEAT_EXT_WINDOW;
 
 		put_unaligned_le32(feat_mask, rsp->data);
 		l2cap_send_cmd(conn, cmd->ident,
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index aa2f2f0..4b388b7 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -331,7 +331,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
 		opts.mode     = chan->mode;
 		opts.fcs      = chan->fcs;
 		opts.max_tx   = chan->max_tx;
-		opts.txwin_size = (__u16)chan->tx_win;
+		opts.txwin_size = chan->tx_win;
 
 		len = min_t(unsigned int, len, sizeof(opts));
 		if (copy_to_user(optval, (char *) &opts, len))
@@ -501,7 +501,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 		opts.mode     = chan->mode;
 		opts.fcs      = chan->fcs;
 		opts.max_tx   = chan->max_tx;
-		opts.txwin_size = (__u16)chan->tx_win;
+		opts.txwin_size = chan->tx_win;
 
 		len = min_t(unsigned int, sizeof(opts), optlen);
 		if (copy_from_user((char *) &opts, optval, len)) {
@@ -509,7 +509,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 			break;
 		}
 
-		if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+		if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
 			err = -EINVAL;
 			break;
 		}
@@ -533,7 +533,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
 		chan->omtu = opts.omtu;
 		chan->fcs  = opts.fcs;
 		chan->max_tx = opts.max_tx;
-		chan->tx_win = (__u8)opts.txwin_size;
+		chan->tx_win = opts.txwin_size;
 		break;
 
 	case L2CAP_LM:
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 03/16] Bluetooth: EWS: adds ext control field bit mask
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 01/16] Bluetooth: clean up spaces in L2CAP header Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 02/16] Bluetooth: EWS: extended window size option support Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 04/16] Bluetooth: EWS: rewrite handling Supervisory (S) bits Emeltchenko Andrei
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds extended control field bit masks and rearrange defines to logical
groups: masks, flags and shift groups.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   41 +++++++++++++++++++++++++++++------------
 1 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 51998ff..fa7edab 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -109,18 +109,35 @@ struct l2cap_conninfo {
 #define L2CAP_FCS_CRC16		0x01
 
 /* L2CAP Control Field bit masks */
-#define L2CAP_CTRL_SAR               0xC000
-#define L2CAP_CTRL_REQSEQ            0x3F00
-#define L2CAP_CTRL_TXSEQ             0x007E
-#define L2CAP_CTRL_RETRANS           0x0080
-#define L2CAP_CTRL_FINAL             0x0080
-#define L2CAP_CTRL_POLL              0x0010
-#define L2CAP_CTRL_SUPERVISE         0x000C
-#define L2CAP_CTRL_FRAME_TYPE        0x0001 /* I- or S-Frame */
-
-#define L2CAP_CTRL_TXSEQ_SHIFT      1
-#define L2CAP_CTRL_REQSEQ_SHIFT     8
-#define L2CAP_CTRL_SAR_SHIFT       14
+#define L2CAP_CTRL_SAR			0xC000
+#define L2CAP_CTRL_REQSEQ		0x3F00
+#define L2CAP_CTRL_TXSEQ		0x007E
+#define L2CAP_CTRL_SUPERVISE		0x000C
+
+#define L2CAP_CTRL_RETRANS		0x0080
+#define L2CAP_CTRL_FINAL		0x0080
+#define L2CAP_CTRL_POLL			0x0010
+#define L2CAP_CTRL_FRAME_TYPE		0x0001 /* I- or S-Frame */
+
+#define L2CAP_CTRL_TXSEQ_SHIFT		1
+#define L2CAP_CTRL_SUPER_SHIFT		2
+#define L2CAP_CTRL_REQSEQ_SHIFT		8
+#define L2CAP_CTRL_SAR_SHIFT		14
+
+/* L2CAP Extended Control Field bit mask */
+#define L2CAP_EXT_CTRL_TXSEQ		0xFFFC0000
+#define L2CAP_EXT_CTRL_SAR		0x00030000
+#define L2CAP_EXT_CTRL_SUPERVISE	0x00030000
+#define L2CAP_EXT_CTRL_REQSEQ		0x0000FFFC
+
+#define L2CAP_EXT_CTRL_POLL		0x00040000
+#define L2CAP_EXT_CTRL_FINAL		0x00000002
+#define L2CAP_EXT_CTRL_FRAME_TYPE	0x00000001 /* I- or S-Frame */
+
+#define L2CAP_EXT_CTRL_REQSEQ_SHIFT	2
+#define L2CAP_EXT_CTRL_SAR_SHIFT	16
+#define L2CAP_EXT_CTRL_SUPER_SHIFT	16
+#define L2CAP_EXT_CTRL_TXSEQ_SHIFT	18
 
 /* L2CAP Supervisory Function */
 #define L2CAP_SUPER_RCV_READY           0x0000
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 04/16] Bluetooth: EWS: rewrite handling Supervisory (S) bits
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (2 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 03/16] Bluetooth: EWS: adds ext control field bit mask Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 05/16] Bluetooth: EWS: rewrite handling SAR bits Emeltchenko Andrei
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Supervisory bits occupy different windows in standard / extended control
fields. Convert hardcoded masks to relative ones and use shift to access
S-bit window.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   27 +++++++++++++++++++++++----
 net/bluetooth/l2cap_core.c    |   41 ++++++++++++++++++++++-------------------
 2 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fa7edab..f24f5cf 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -140,10 +140,10 @@ struct l2cap_conninfo {
 #define L2CAP_EXT_CTRL_TXSEQ_SHIFT	18
 
 /* L2CAP Supervisory Function */
-#define L2CAP_SUPER_RCV_READY           0x0000
-#define L2CAP_SUPER_REJECT              0x0004
-#define L2CAP_SUPER_RCV_NOT_READY       0x0008
-#define L2CAP_SUPER_SELECT_REJECT       0x000C
+#define L2CAP_SUPER_RR		0x00
+#define L2CAP_SUPER_REJ		0x01
+#define L2CAP_SUPER_RNR		0x02
+#define L2CAP_SUPER_SREJ	0x03
 
 /* L2CAP Segmentation and Reassembly */
 #define L2CAP_SDU_UNSEGMENTED       0x0000
@@ -518,6 +518,25 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
+static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >>
+						L2CAP_EXT_CTRL_SUPER_SHIFT;
+	else
+		return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
+}
+
+static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) &
+						L2CAP_EXT_CTRL_SUPERVISE;
+	else
+		return (super << L2CAP_CTRL_SUPER_SHIFT) &
+							L2CAP_CTRL_SUPERVISE;
+}
+
 extern int disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6e34312..93b5da6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -613,10 +613,10 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 {
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
+		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
 		set_bit(CONN_RNR_SENT, &chan->conn_state);
 	} else
-		control |= L2CAP_SUPER_RCV_READY;
+		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 
 	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
@@ -1408,7 +1408,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
+		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
 		set_bit(CONN_RNR_SENT, &chan->conn_state);
 		l2cap_send_sframe(chan, control);
 		return;
@@ -1417,7 +1417,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 	if (l2cap_ertm_send(chan) > 0)
 		return;
 
-	control |= L2CAP_SUPER_RCV_READY;
+	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 	l2cap_send_sframe(chan, control);
 }
 
@@ -1426,7 +1426,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
 	struct srej_list *tail;
 	u16 control;
 
-	control = L2CAP_SUPER_SELECT_REJECT;
+	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
 	control |= L2CAP_CTRL_FINAL;
 
 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
@@ -3119,7 +3119,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
+		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
 		l2cap_send_sframe(chan, control);
 		set_bit(CONN_RNR_SENT, &chan->conn_state);
 	}
@@ -3131,7 +3131,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 
 	if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
 			chan->frames_sent == 0) {
-		control |= L2CAP_SUPER_RCV_READY;
+		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 		l2cap_send_sframe(chan, control);
 	}
 }
@@ -3287,7 +3287,7 @@ static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
 
 	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	control |= L2CAP_SUPER_RCV_NOT_READY;
+	control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
 	l2cap_send_sframe(chan, control);
 
 	set_bit(CONN_RNR_SENT, &chan->conn_state);
@@ -3303,7 +3303,8 @@ static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
 		goto done;
 
 	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+	control |= L2CAP_CTRL_POLL;
+	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 	l2cap_send_sframe(chan, control);
 	chan->retry_count = 1;
 
@@ -3367,7 +3368,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 			kfree(l);
 			return;
 		}
-		control = L2CAP_SUPER_SELECT_REJECT;
+		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
 		control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 		l2cap_send_sframe(chan, control);
 		list_del(&l->list);
@@ -3381,7 +3382,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 	u16 control;
 
 	while (tx_seq != chan->expected_tx_seq) {
-		control = L2CAP_SUPER_SELECT_REJECT;
+		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
 		control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 		l2cap_send_sframe(chan, control);
 
@@ -3645,10 +3646,12 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c
 		return;
 	}
 
-	if (rx_control & L2CAP_CTRL_POLL)
+	if (rx_control & L2CAP_CTRL_POLL) {
 		l2cap_send_srejtail(chan);
-	else
-		l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);
+	} else {
+		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
+		l2cap_send_sframe(chan, rx_control);
+	}
 }
 
 static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
@@ -3663,20 +3666,20 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
 		clear_bit(CONN_WAIT_F, &chan->conn_state);
 	}
 
-	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
-	case L2CAP_SUPER_RCV_READY:
+	switch (__get_ctrl_super(chan, rx_control)) {
+	case L2CAP_SUPER_RR:
 		l2cap_data_channel_rrframe(chan, rx_control);
 		break;
 
-	case L2CAP_SUPER_REJECT:
+	case L2CAP_SUPER_REJ:
 		l2cap_data_channel_rejframe(chan, rx_control);
 		break;
 
-	case L2CAP_SUPER_SELECT_REJECT:
+	case L2CAP_SUPER_SREJ:
 		l2cap_data_channel_srejframe(chan, rx_control);
 		break;
 
-	case L2CAP_SUPER_RCV_NOT_READY:
+	case L2CAP_SUPER_RNR:
 		l2cap_data_channel_rnrframe(chan, rx_control);
 		break;
 	}
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 05/16] Bluetooth: EWS: rewrite handling SAR bits
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (3 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 04/16] Bluetooth: EWS: rewrite handling Supervisory (S) bits Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 06/16] Bluetooth: EWS: rewrite reqseq calculation Emeltchenko Andrei
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Segmentation and Reassembly (SAR) occupies different windows in standard and
extended control fields. Convert hardcoded masks to relative ones and use shift
to access SAR bits.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   37 ++++++++++++++++++++++++++++++++-----
 net/bluetooth/l2cap_core.c    |   30 +++++++++++++++---------------
 2 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f24f5cf..0759ac6 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -146,10 +146,10 @@ struct l2cap_conninfo {
 #define L2CAP_SUPER_SREJ	0x03
 
 /* L2CAP Segmentation and Reassembly */
-#define L2CAP_SDU_UNSEGMENTED       0x0000
-#define L2CAP_SDU_START             0x4000
-#define L2CAP_SDU_END               0x8000
-#define L2CAP_SDU_CONTINUE          0xC000
+#define L2CAP_SAR_UNSEGMENTED	0x00
+#define L2CAP_SAR_START		0x01
+#define L2CAP_SAR_END		0x02
+#define L2CAP_SAR_CONTINUE	0x03
 
 /* L2CAP Command rej. reasons */
 #define L2CAP_REJ_NOT_UNDERSTOOD	0x0000
@@ -516,7 +516,34 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 #define __get_reqseq(ctrl)	(((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
 #define __is_iframe(ctrl)	(!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
-#define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
+static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
+	else
+		return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
+}
+
+static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR;
+	else
+		return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR;
+}
+
+static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl)
+{
+	return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START;
+}
+
+static inline __u32 __get_sar_mask(struct l2cap_chan *chan)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return L2CAP_EXT_CTRL_SAR;
+	else
+		return L2CAP_CTRL_SAR;
+}
 
 static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl)
 {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 93b5da6..9ee42ba 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1311,7 +1311,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 	tx_skb = skb_clone(skb, GFP_ATOMIC);
 	bt_cb(skb)->retries++;
 	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-	control &= L2CAP_CTRL_SAR;
+	control &= __get_sar_mask(chan);
 
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_FINAL;
@@ -1351,7 +1351,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 		bt_cb(skb)->retries++;
 
 		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-		control &= L2CAP_CTRL_SAR;
+		control &= __get_sar_mask(chan);
 
 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 			control |= L2CAP_CTRL_FINAL;
@@ -1582,7 +1582,7 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
 	size_t size = 0;
 
 	skb_queue_head_init(&sar_queue);
-	control = L2CAP_SDU_START;
+	control = __set_ctrl_sar(chan, L2CAP_SAR_START);
 	skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
 	if (IS_ERR(skb))
 		return PTR_ERR(skb);
@@ -1595,10 +1595,10 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
 		size_t buflen;
 
 		if (len > chan->remote_mps) {
-			control = L2CAP_SDU_CONTINUE;
+			control = __set_ctrl_sar(chan, L2CAP_SAR_CONTINUE);
 			buflen = chan->remote_mps;
 		} else {
-			control = L2CAP_SDU_END;
+			control = __set_ctrl_sar(chan, L2CAP_SAR_END);
 			buflen = len;
 		}
 
@@ -1654,7 +1654,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
 	case L2CAP_MODE_STREAMING:
 		/* Entire SDU fits into one PDU */
 		if (len <= chan->remote_mps) {
-			control = L2CAP_SDU_UNSEGMENTED;
+			control = __set_ctrl_sar(chan, L2CAP_SAR_UNSEGMENTED);
 			skb = l2cap_create_iframe_pdu(chan, msg, len, control,
 									0);
 			if (IS_ERR(skb))
@@ -3201,15 +3201,15 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
 {
 	int err = -EINVAL;
 
-	switch (control & L2CAP_CTRL_SAR) {
-	case L2CAP_SDU_UNSEGMENTED:
+	switch (__get_ctrl_sar(chan, control)) {
+	case L2CAP_SAR_UNSEGMENTED:
 		if (chan->sdu)
 			break;
 
 		err = chan->ops->recv(chan->data, skb);
 		break;
 
-	case L2CAP_SDU_START:
+	case L2CAP_SAR_START:
 		if (chan->sdu)
 			break;
 
@@ -3231,7 +3231,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
 		err = 0;
 		break;
 
-	case L2CAP_SDU_CONTINUE:
+	case L2CAP_SAR_CONTINUE:
 		if (!chan->sdu)
 			break;
 
@@ -3245,7 +3245,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
 		err = 0;
 		break;
 
-	case L2CAP_SDU_END:
+	case L2CAP_SAR_END:
 		if (!chan->sdu)
 			break;
 
@@ -3343,7 +3343,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
 			break;
 
 		skb = skb_dequeue(&chan->srej_q);
-		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
+		control = __set_ctrl_sar(chan, bt_cb(skb)->sar);
 		err = l2cap_reassemble_sdu(chan, skb, control);
 
 		if (err < 0) {
@@ -3398,7 +3398,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 {
 	u8 tx_seq = __get_txseq(rx_control);
 	u8 req_seq = __get_reqseq(rx_control);
-	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
+	u8 sar = __get_ctrl_sar(chan, rx_control);
 	int tx_seq_offset, expected_tx_seq_offset;
 	int num_to_ack = (chan->tx_win/6) + 1;
 	int err = 0;
@@ -3707,7 +3707,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 	if (l2cap_check_fcs(chan, skb))
 		goto drop;
 
-	if (__is_sar_start(control) && __is_iframe(control))
+	if (__is_sar_start(chan, control) && __is_iframe(control))
 		len -= 2;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
@@ -3811,7 +3811,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (l2cap_check_fcs(chan, skb))
 			goto drop;
 
-		if (__is_sar_start(control))
+		if (__is_sar_start(chan, control))
 			len -= 2;
 
 		if (chan->fcs == L2CAP_FCS_CRC16)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 06/16] Bluetooth: EWS: rewrite reqseq calculation
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (4 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 05/16] Bluetooth: EWS: rewrite handling SAR bits Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 07/16] Bluetooth: EWS: rewrite L2CAP ERTM txseq calculation Emeltchenko Andrei
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

reqseq calculation uses now information about control field type.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   20 +++++++++++++++++-
 net/bluetooth/l2cap_core.c    |   42 ++++++++++++++++++++--------------------
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0759ac6..57b64bb 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -365,11 +365,11 @@ struct l2cap_chan {
 	__u8		next_tx_seq;
 	__u8		expected_ack_seq;
 	__u8		expected_tx_seq;
-	__u8		buffer_seq;
 	__u8		buffer_seq_srej;
 	__u8		srej_save_reqseq;
 	__u8		frames_sent;
 	__u8		unacked_frames;
+	__u16		buffer_seq;
 	__u8		retry_count;
 	__u8		num_acked;
 	__u16		sdu_len;
@@ -512,8 +512,24 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 	return sub == ch->remote_tx_win;
 }
 
+static inline __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (ctrl & L2CAP_EXT_CTRL_REQSEQ) >>
+						L2CAP_EXT_CTRL_REQSEQ_SHIFT;
+	else
+		return (ctrl & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
+}
+
+static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) &
+							L2CAP_EXT_CTRL_REQSEQ;
+	else
+		return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ;
+}
 #define __get_txseq(ctrl)	(((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
-#define __get_reqseq(ctrl)	(((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
 #define __is_iframe(ctrl)	(!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9ee42ba..f35eb73 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -618,7 +618,7 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 	} else
 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 
-	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= __set_reqseq(chan, chan->buffer_seq);
 
 	l2cap_send_sframe(chan, control);
 }
@@ -1316,8 +1316,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_FINAL;
 
-	control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
-			| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+	control |= __set_reqseq(chan, chan->buffer_seq);
+	control |= tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
 
 	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
@@ -1356,8 +1356,8 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 			control |= L2CAP_CTRL_FINAL;
 
-		control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
-				| (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+		control |= __set_reqseq(chan, chan->buffer_seq);
+		control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
 
@@ -1405,7 +1405,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 {
 	u16 control = 0;
 
-	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= __set_reqseq(chan, chan->buffer_seq);
 
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
@@ -1430,7 +1430,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
 	control |= L2CAP_CTRL_FINAL;
 
 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
-	control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= __set_reqseq(chan, tail->tx_seq);
 
 	l2cap_send_sframe(chan, control);
 }
@@ -3116,7 +3116,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 
 	chan->frames_sent = 0;
 
-	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= __set_reqseq(chan, chan->buffer_seq);
 
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
@@ -3286,7 +3286,7 @@ static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
 
 	set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
 
-	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control = __set_reqseq(chan, chan->buffer_seq);
 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
 	l2cap_send_sframe(chan, control);
 
@@ -3302,7 +3302,7 @@ static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
 		goto done;
 
-	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control = __set_reqseq(chan, chan->buffer_seq);
 	control |= L2CAP_CTRL_POLL;
 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 	l2cap_send_sframe(chan, control);
@@ -3369,7 +3369,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 			return;
 		}
 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
-		control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+		control |= __set_reqseq(chan, l->tx_seq);
 		l2cap_send_sframe(chan, control);
 		list_del(&l->list);
 		list_add_tail(&l->list, &chan->srej_l);
@@ -3383,7 +3383,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 
 	while (tx_seq != chan->expected_tx_seq) {
 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
-		control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+		control |= __set_reqseq(chan, chan->expected_tx_seq);
 		l2cap_send_sframe(chan, control);
 
 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
@@ -3397,7 +3397,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
 {
 	u8 tx_seq = __get_txseq(rx_control);
-	u8 req_seq = __get_reqseq(rx_control);
+	u16 req_seq = __get_reqseq(chan, rx_control);
 	u8 sar = __get_ctrl_sar(chan, rx_control);
 	int tx_seq_offset, expected_tx_seq_offset;
 	int num_to_ack = (chan->tx_win/6) + 1;
@@ -3531,10 +3531,10 @@ drop:
 
 static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
 {
-	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),
-						rx_control);
+	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
+				__get_reqseq(chan, rx_control), rx_control);
 
-	chan->expected_ack_seq = __get_reqseq(rx_control);
+	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
 	l2cap_drop_acked_frames(chan);
 
 	if (rx_control & L2CAP_CTRL_POLL) {
@@ -3571,7 +3571,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
 
 static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
 {
-	u8 tx_seq = __get_reqseq(rx_control);
+	u16 tx_seq = __get_reqseq(chan, rx_control);
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
@@ -3592,7 +3592,7 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
 }
 static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
 {
-	u8 tx_seq = __get_reqseq(rx_control);
+	u16 tx_seq = __get_reqseq(chan, rx_control);
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
@@ -3628,7 +3628,7 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 
 static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
 {
-	u8 tx_seq = __get_reqseq(rx_control);
+	u16 tx_seq = __get_reqseq(chan, rx_control);
 
 	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
@@ -3692,7 +3692,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 	u16 control;
-	u8 req_seq;
+	u16 req_seq;
 	int len, next_tx_seq_offset, req_seq_offset;
 
 	control = get_unaligned_le16(skb->data);
@@ -3718,7 +3718,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 	}
 
-	req_seq = __get_reqseq(control);
+	req_seq = __get_reqseq(chan, control);
 	req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
 	if (req_seq_offset < 0)
 		req_seq_offset += 64;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 07/16] Bluetooth: EWS: rewrite L2CAP ERTM txseq calculation
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (5 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 06/16] Bluetooth: EWS: rewrite reqseq calculation Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 08/16] Bluetooth: EWS: rewrite check frame type function Emeltchenko Andrei
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

L2CAP ERTM txseq calculation uses now information about control field type.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   36 +++++++++++++++++++++++++++---------
 net/bluetooth/l2cap_core.c    |   22 +++++++++++-----------
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 57b64bb..3ca24af 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -316,7 +316,7 @@ struct l2cap_conn_param_update_rsp {
 
 /* ----- L2CAP channels and connections ----- */
 struct srej_list {
-	__u8	tx_seq;
+	__u16	tx_seq;
 	struct list_head list;
 };
 
@@ -362,14 +362,14 @@ struct l2cap_chan {
 	unsigned long	conn_state;
 	unsigned long	flags;
 
-	__u8		next_tx_seq;
-	__u8		expected_ack_seq;
-	__u8		expected_tx_seq;
-	__u8		buffer_seq_srej;
-	__u8		srej_save_reqseq;
-	__u8		frames_sent;
-	__u8		unacked_frames;
+	__u16		next_tx_seq;
+	__u16		expected_ack_seq;
+	__u16		expected_tx_seq;
 	__u16		buffer_seq;
+	__u16		buffer_seq_srej;
+	__u16		srej_save_reqseq;
+	__u16		frames_sent;
+	__u16		unacked_frames;
 	__u8		retry_count;
 	__u8		num_acked;
 	__u16		sdu_len;
@@ -529,7 +529,25 @@ static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq)
 	else
 		return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ;
 }
-#define __get_txseq(ctrl)	(((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
+
+static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (ctrl & L2CAP_EXT_CTRL_TXSEQ) >>
+						L2CAP_EXT_CTRL_TXSEQ_SHIFT;
+	else
+		return (ctrl & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
+}
+
+static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) &
+							L2CAP_EXT_CTRL_TXSEQ;
+	else
+		return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ;
+}
+
 #define __is_iframe(ctrl)	(!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f35eb73..1c367d6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1270,7 +1270,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
 
 	while ((skb = skb_dequeue(&chan->tx_q))) {
 		control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
-		control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+		control |= __set_txseq(chan, chan->next_tx_seq);
 		put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
 
 		if (chan->fcs == L2CAP_FCS_CRC16) {
@@ -1284,7 +1284,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
 	}
 }
 
-static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
+static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct sk_buff *skb, *tx_skb;
 	u16 control, fcs;
@@ -1317,7 +1317,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 		control |= L2CAP_CTRL_FINAL;
 
 	control |= __set_reqseq(chan, chan->buffer_seq);
-	control |= tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+	control |= __set_txseq(chan, tx_seq);
 
 	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
@@ -1357,7 +1357,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 			control |= L2CAP_CTRL_FINAL;
 
 		control |= __set_reqseq(chan, chan->buffer_seq);
-		control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+		control |= __set_txseq(chan, chan->next_tx_seq);
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
 
@@ -3136,7 +3136,7 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 	}
 }
 
-static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)
+static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u16 tx_seq, u8 sar)
 {
 	struct sk_buff *next_skb;
 	int tx_seq_offset, next_tx_seq_offset;
@@ -3330,7 +3330,7 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
 	}
 }
 
-static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
+static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct sk_buff *skb;
 	u16 control;
@@ -3357,7 +3357,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
 	}
 }
 
-static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
+static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct srej_list *l, *tmp;
 	u16 control;
@@ -3376,7 +3376,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 	}
 }
 
-static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
+static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct srej_list *new;
 	u16 control;
@@ -3396,7 +3396,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
 
 static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
 {
-	u8 tx_seq = __get_txseq(rx_control);
+	u16 tx_seq = __get_txseq(chan, rx_control);
 	u16 req_seq = __get_reqseq(chan, rx_control);
 	u8 sar = __get_ctrl_sar(chan, rx_control);
 	int tx_seq_offset, expected_tx_seq_offset;
@@ -3763,7 +3763,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 	struct l2cap_chan *chan;
 	struct sock *sk = NULL;
 	u16 control;
-	u8 tx_seq;
+	u16 tx_seq;
 	int len;
 
 	chan = l2cap_get_chan_by_scid(conn, cid);
@@ -3820,7 +3820,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (len > chan->mps || len < 0 || __is_sframe(control))
 			goto drop;
 
-		tx_seq = __get_txseq(control);
+		tx_seq = __get_txseq(chan, control);
 
 		if (chan->expected_tx_seq != tx_seq) {
 			/* Frame(s) missing - must discard partial SDU */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 08/16] Bluetooth: EWS: rewrite check frame type function
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (6 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 07/16] Bluetooth: EWS: rewrite L2CAP ERTM txseq calculation Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 09/16] Bluetooth: EWS: rewrite handling FINAL (F) bit Emeltchenko Andrei
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Check frame function uses now information about control field type.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   18 ++++++++++++++++--
 net/bluetooth/l2cap_core.c    |    9 +++++----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 3ca24af..9444dce 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -548,8 +548,22 @@ static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq)
 		return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ;
 }
 
-#define __is_iframe(ctrl)	(!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
-#define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
+static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE;
+	else
+		return ctrl & L2CAP_CTRL_FRAME_TYPE;
+}
+
+static inline __u32 __set_sframe(struct l2cap_chan *chan)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return L2CAP_EXT_CTRL_FRAME_TYPE;
+	else
+		return L2CAP_CTRL_FRAME_TYPE;
+}
+
 static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl)
 {
 	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 1c367d6..9262a00 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -578,7 +578,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	BT_DBG("chan %p, control 0x%2.2x", chan, control);
 
 	count = min_t(unsigned int, conn->mtu, hlen);
-	control |= L2CAP_CTRL_FRAME_TYPE;
+
+	control |= __set_sframe(chan);
 
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_FINAL;
@@ -3707,7 +3708,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 	if (l2cap_check_fcs(chan, skb))
 		goto drop;
 
-	if (__is_sar_start(chan, control) && __is_iframe(control))
+	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
 		len -= 2;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
@@ -3734,7 +3735,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 	}
 
-	if (__is_iframe(control)) {
+	if (!__is_sframe(chan, control)) {
 		if (len < 0) {
 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
 			goto drop;
@@ -3817,7 +3818,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (chan->fcs == L2CAP_FCS_CRC16)
 			len -= 2;
 
-		if (len > chan->mps || len < 0 || __is_sframe(control))
+		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
 			goto drop;
 
 		tx_seq = __get_txseq(chan, control);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 09/16] Bluetooth: EWS: rewrite handling FINAL (F) bit
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (7 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 08/16] Bluetooth: EWS: rewrite check frame type function Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit Emeltchenko Andrei
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Handle final (F) bit in L2CAP using information about control field type.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   15 +++++++++++++++
 net/bluetooth/l2cap_core.c    |   20 ++++++++++----------
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 9444dce..3110c43 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -612,6 +612,21 @@ static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super)
 							L2CAP_CTRL_SUPERVISE;
 }
 
+static inline __u32 __set_ctrl_final(struct l2cap_chan *chan)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return L2CAP_EXT_CTRL_FINAL;
+	else
+		return L2CAP_CTRL_FINAL;
+}
+
+static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return ctrl & L2CAP_EXT_CTRL_FINAL;
+	else
+		return ctrl & L2CAP_CTRL_FINAL;
+}
 extern int disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9262a00..c500d1c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -582,7 +582,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	control |= __set_sframe(chan);
 
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
-		control |= L2CAP_CTRL_FINAL;
+		control |= __set_ctrl_final(chan);
 
 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
 		control |= L2CAP_CTRL_POLL;
@@ -1315,7 +1315,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 	control &= __get_sar_mask(chan);
 
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
-		control |= L2CAP_CTRL_FINAL;
+		control |= __set_ctrl_final(chan);
 
 	control |= __set_reqseq(chan, chan->buffer_seq);
 	control |= __set_txseq(chan, tx_seq);
@@ -1355,7 +1355,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 		control &= __get_sar_mask(chan);
 
 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
-			control |= L2CAP_CTRL_FINAL;
+			control |= __set_ctrl_final(chan);
 
 		control |= __set_reqseq(chan, chan->buffer_seq);
 		control |= __set_txseq(chan, chan->next_tx_seq);
@@ -1428,7 +1428,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
 	u16 control;
 
 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
-	control |= L2CAP_CTRL_FINAL;
+	control |= __set_ctrl_final(chan);
 
 	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);
 	control |= __set_reqseq(chan, tail->tx_seq);
@@ -3407,7 +3407,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
 							tx_seq, rx_control);
 
-	if (L2CAP_CTRL_FINAL & rx_control &&
+	if (__is_ctrl_final(chan, rx_control) &&
 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
 		__clear_monitor_timer(chan);
 		if (chan->unacked_frames > 0)
@@ -3512,7 +3512,7 @@ expected:
 		return err;
 	}
 
-	if (rx_control & L2CAP_CTRL_FINAL) {
+	if (__is_ctrl_final(chan, rx_control)) {
 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
 			l2cap_retransmit_frames(chan);
 	}
@@ -3551,7 +3551,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
 			l2cap_send_i_or_rr_or_rnr(chan);
 		}
 
-	} else if (rx_control & L2CAP_CTRL_FINAL) {
+	} else if (__is_ctrl_final(chan, rx_control)) {
 		clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
@@ -3581,7 +3581,7 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
 	chan->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(chan);
 
-	if (rx_control & L2CAP_CTRL_FINAL) {
+	if (__is_ctrl_final(chan, rx_control)) {
 		if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
 			l2cap_retransmit_frames(chan);
 	} else {
@@ -3612,7 +3612,7 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 			chan->srej_save_reqseq = tx_seq;
 			set_bit(CONN_SREJ_ACT, &chan->conn_state);
 		}
-	} else if (rx_control & L2CAP_CTRL_FINAL) {
+	} else if (__is_ctrl_final(chan, rx_control)) {
 		if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
 				chan->srej_save_reqseq == tx_seq)
 			clear_bit(CONN_SREJ_ACT, &chan->conn_state);
@@ -3659,7 +3659,7 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
 {
 	BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
 
-	if (L2CAP_CTRL_FINAL & rx_control &&
+	if (__is_ctrl_final(chan, rx_control) &&
 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
 		__clear_monitor_timer(chan);
 		if (chan->unacked_frames > 0)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (8 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 09/16] Bluetooth: EWS: rewrite handling FINAL (F) bit Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-13 19:47   ` Gustavo Padovan
  2011-10-11 10:37 ` [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields Emeltchenko Andrei
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Handle POLL (P) bit in L2CAP ERTM using information about control field type.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   16 ++++++++++++++++
 net/bluetooth/l2cap_core.c    |   14 +++++++-------
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 3110c43..67a2fdb 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -627,6 +627,22 @@ static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl)
 	else
 		return ctrl & L2CAP_CTRL_FINAL;
 }
+
+static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return L2CAP_EXT_CTRL_POLL;
+	else
+		return L2CAP_CTRL_POLL;
+}
+
+static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return ctrl & L2CAP_EXT_CTRL_POLL;
+	else
+		return ctrl & L2CAP_CTRL_POLL;
+}
 extern int disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c500d1c..97aa545 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -585,7 +585,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 		control |= __set_ctrl_final(chan);
 
 	if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
-		control |= L2CAP_CTRL_POLL;
+		control |= __set_ctrl_poll(chan);
 
 	skb = bt_skb_alloc(count, GFP_ATOMIC);
 	if (!skb)
@@ -3304,7 +3304,7 @@ static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
 		goto done;
 
 	control = __set_reqseq(chan, chan->buffer_seq);
-	control |= L2CAP_CTRL_POLL;
+	control |= __set_ctrl_poll(chan);
 	control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
 	l2cap_send_sframe(chan, control);
 	chan->retry_count = 1;
@@ -3538,7 +3538,7 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
 	l2cap_drop_acked_frames(chan);
 
-	if (rx_control & L2CAP_CTRL_POLL) {
+	if (__is_ctrl_poll(chan, rx_control)) {
 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
 		if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
 			if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
@@ -3599,7 +3599,7 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 
 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
-	if (rx_control & L2CAP_CTRL_POLL) {
+	if (__is_ctrl_poll(chan, rx_control)) {
 		chan->expected_ack_seq = tx_seq;
 		l2cap_drop_acked_frames(chan);
 
@@ -3637,17 +3637,17 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c
 	chan->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(chan);
 
-	if (rx_control & L2CAP_CTRL_POLL)
+	if (__is_ctrl_poll(chan, rx_control))
 		set_bit(CONN_SEND_FBIT, &chan->conn_state);
 
 	if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
 		__clear_retrans_timer(chan);
-		if (rx_control & L2CAP_CTRL_POLL)
+		if (__is_ctrl_poll(chan, rx_control))
 			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
 		return;
 	}
 
-	if (rx_control & L2CAP_CTRL_POLL) {
+	if (__is_ctrl_poll(chan, rx_control)) {
 		l2cap_send_srejtail(chan);
 	} else {
 		rx_control = __set_ctrl_super(chan, L2CAP_SUPER_RR);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (9 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-13 19:49   ` Gustavo Padovan
  2011-10-11 10:37 ` [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size Emeltchenko Andrei
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

There are three different Control Field formats: the Standard Control
Field, the Enhanced Control Field, and the Extended Control Field.
Patch adds function to handle all those fields seamlessly.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |   43 +++++++++++++++++++
 net/bluetooth/l2cap_core.c    |   93 +++++++++++++++++++++-------------------
 2 files changed, 92 insertions(+), 44 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 67a2fdb..3a5f4c0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -27,6 +27,8 @@
 #ifndef __L2CAP_H
 #define __L2CAP_H
 
+#include <asm/unaligned.h>
+
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU		672
 #define L2CAP_DEFAULT_MIN_MTU		48
@@ -643,6 +645,47 @@ static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
 	else
 		return ctrl & L2CAP_CTRL_POLL;
 }
+
+static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return get_unaligned_le32(p);
+	else
+		return get_unaligned_le16(p);
+}
+
+static inline __u32 __get_control_pull(struct l2cap_chan *chan,
+		struct sk_buff *skb, void *p)
+{
+	__u32 ctrl;
+
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
+		ctrl = get_unaligned_le32(p);
+		skb_pull(skb, 4);
+	} else {
+		ctrl = get_unaligned_le16(p);
+		skb_pull(skb, 2);
+	}
+
+	return ctrl;
+}
+
+static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return put_unaligned_le32(control, p);
+	else
+		return put_unaligned_le16(control, p);
+}
+
+static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
+{
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		return put_unaligned_le32(control, skb_put(p, 4));
+	else
+		return put_unaligned_le16(control, skb_put(p, 2));
+}
+
 extern int disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 97aa545..6a5d1d6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -561,7 +561,7 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
 	hci_send_acl(conn->hcon, skb, flags);
 }
 
-static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
+static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
 {
 	struct sk_buff *skb;
 	struct l2cap_hdr *lh;
@@ -575,7 +575,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	if (chan->fcs == L2CAP_FCS_CRC16)
 		hlen += 2;
 
-	BT_DBG("chan %p, control 0x%2.2x", chan, control);
+	BT_DBG("chan %p, control 0x%8.8x", chan, control);
 
 	count = min_t(unsigned int, conn->mtu, hlen);
 
@@ -594,7 +594,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
 	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
 	lh->cid = cpu_to_le16(chan->dcid);
-	put_unaligned_le16(control, skb_put(skb, 2));
+
+	__put_control_put(chan, control, skb);
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
 		u16 fcs = crc16(0, (u8 *)lh, count - 2);
@@ -611,7 +612,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 	hci_send_acl(chan->conn->hcon, skb, flags);
 }
 
-static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
+static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
 {
 	if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
 		control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
@@ -1267,12 +1268,13 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
 static void l2cap_streaming_send(struct l2cap_chan *chan)
 {
 	struct sk_buff *skb;
-	u16 control, fcs;
+	u32 control;
+	u16 fcs;
 
 	while ((skb = skb_dequeue(&chan->tx_q))) {
-		control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
+		control = __get_control(chan, skb->data + L2CAP_HDR_SIZE);
 		control |= __set_txseq(chan, chan->next_tx_seq);
-		put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
+		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
 
 		if (chan->fcs == L2CAP_FCS_CRC16) {
 			fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
@@ -1288,7 +1290,8 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
 static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct sk_buff *skb, *tx_skb;
-	u16 control, fcs;
+	u16 fcs;
+	u32 control;
 
 	skb = skb_peek(&chan->tx_q);
 	if (!skb)
@@ -1311,7 +1314,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 
 	tx_skb = skb_clone(skb, GFP_ATOMIC);
 	bt_cb(skb)->retries++;
-	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+
+	control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
 	control &= __get_sar_mask(chan);
 
 	if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
@@ -1320,7 +1324,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 	control |= __set_reqseq(chan, chan->buffer_seq);
 	control |= __set_txseq(chan, tx_seq);
 
-	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
 		fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
@@ -1333,7 +1337,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 static int l2cap_ertm_send(struct l2cap_chan *chan)
 {
 	struct sk_buff *skb, *tx_skb;
-	u16 control, fcs;
+	u16 fcs;
+	u32 control;
 	int nsent = 0;
 
 	if (chan->state != BT_CONNECTED)
@@ -1351,7 +1356,7 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 
 		bt_cb(skb)->retries++;
 
-		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+		control = __get_control(chan, tx_skb->data + L2CAP_HDR_SIZE);
 		control &= __get_sar_mask(chan);
 
 		if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
@@ -1359,8 +1364,8 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 
 		control |= __set_reqseq(chan, chan->buffer_seq);
 		control |= __set_txseq(chan, chan->next_tx_seq);
-		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
+		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
 
 		if (chan->fcs == L2CAP_FCS_CRC16) {
 			fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
@@ -1404,7 +1409,7 @@ static int l2cap_retransmit_frames(struct l2cap_chan *chan)
 
 static void l2cap_send_ack(struct l2cap_chan *chan)
 {
-	u16 control = 0;
+	u32 control = 0;
 
 	control |= __set_reqseq(chan, chan->buffer_seq);
 
@@ -1425,7 +1430,7 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 static void l2cap_send_srejtail(struct l2cap_chan *chan)
 {
 	struct srej_list *tail;
-	u16 control;
+	u32 control;
 
 	control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
 	control |= __set_ctrl_final(chan);
@@ -1529,7 +1534,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct ms
 
 static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 						struct msghdr *msg, size_t len,
-						u16 control, u16 sdulen)
+						u32 control, u16 sdulen)
 {
 	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
@@ -1558,7 +1563,9 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
 	lh->cid = cpu_to_le16(chan->dcid);
 	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
-	put_unaligned_le16(control, skb_put(skb, 2));
+
+	__put_control_put(chan, control, skb);
+
 	if (sdulen)
 		put_unaligned_le16(sdulen, skb_put(skb, 2));
 
@@ -1579,7 +1586,7 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
 {
 	struct sk_buff *skb;
 	struct sk_buff_head sar_queue;
-	u16 control;
+	u32 control;
 	size_t size = 0;
 
 	skb_queue_head_init(&sar_queue);
@@ -1623,7 +1630,7 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
 int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
 {
 	struct sk_buff *skb;
-	u16 control;
+	u32 control;
 	int err;
 
 	/* Connectionless channel */
@@ -3113,7 +3120,7 @@ static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
 
 static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 {
-	u16 control = 0;
+	u32 control = 0;
 
 	chan->frames_sent = 0;
 
@@ -3198,7 +3205,7 @@ static void append_skb_frag(struct sk_buff *skb,
 	skb->truesize += new_frag->truesize;
 }
 
-static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
+static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u32 control)
 {
 	int err = -EINVAL;
 
@@ -3281,7 +3288,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u1
 
 static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
 {
-	u16 control;
+	u32 control;
 
 	BT_DBG("chan %p, Enter local busy", chan);
 
@@ -3298,7 +3305,7 @@ static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan)
 
 static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan)
 {
-	u16 control;
+	u32 control;
 
 	if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
 		goto done;
@@ -3334,7 +3341,7 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
 static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct sk_buff *skb;
-	u16 control;
+	u32 control;
 
 	while ((skb = skb_peek(&chan->srej_q)) &&
 			!test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
@@ -3361,7 +3368,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
 static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct srej_list *l, *tmp;
-	u16 control;
+	u32 control;
 
 	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {
 		if (l->tx_seq == tx_seq) {
@@ -3380,7 +3387,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 {
 	struct srej_list *new;
-	u16 control;
+	u32 control;
 
 	while (tx_seq != chan->expected_tx_seq) {
 		control = __set_ctrl_super(chan, L2CAP_SUPER_SREJ);
@@ -3395,7 +3402,7 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
 }
 
-static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
+static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
 {
 	u16 tx_seq = __get_txseq(chan, rx_control);
 	u16 req_seq = __get_reqseq(chan, rx_control);
@@ -3404,7 +3411,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 	int num_to_ack = (chan->tx_win/6) + 1;
 	int err = 0;
 
-	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
+	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%8.8x", chan, skb->len,
 							tx_seq, rx_control);
 
 	if (__is_ctrl_final(chan, rx_control) &&
@@ -3530,9 +3537,9 @@ drop:
 	return 0;
 }
 
-static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)
+static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u32 rx_control)
 {
-	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan,
+	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan,
 				__get_reqseq(chan, rx_control), rx_control);
 
 	chan->expected_ack_seq = __get_reqseq(chan, rx_control);
@@ -3570,11 +3577,11 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
 	}
 }
 
-static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)
+static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u32 rx_control)
 {
 	u16 tx_seq = __get_reqseq(chan, rx_control);
 
-	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
+	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
 
 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
@@ -3591,11 +3598,11 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
 			set_bit(CONN_REJ_ACT, &chan->conn_state);
 	}
 }
-static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
+static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u32 rx_control)
 {
 	u16 tx_seq = __get_reqseq(chan, rx_control);
 
-	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
+	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
 
 	clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
@@ -3627,11 +3634,11 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 	}
 }
 
-static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)
+static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u32 rx_control)
 {
 	u16 tx_seq = __get_reqseq(chan, rx_control);
 
-	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
+	BT_DBG("chan %p, req_seq %d ctrl 0x%8.8x", chan, tx_seq, rx_control);
 
 	set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 	chan->expected_ack_seq = tx_seq;
@@ -3655,9 +3662,9 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c
 	}
 }
 
-static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
+static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
 {
-	BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
+	BT_DBG("chan %p rx_control 0x%8.8x len %d", chan, rx_control, skb->len);
 
 	if (__is_ctrl_final(chan, rx_control) &&
 			test_bit(CONN_WAIT_F, &chan->conn_state)) {
@@ -3692,12 +3699,11 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-	u16 control;
+	u32 control;
 	u16 req_seq;
 	int len, next_tx_seq_offset, req_seq_offset;
 
-	control = get_unaligned_le16(skb->data);
-	skb_pull(skb, 2);
+	control = __get_control_pull(chan, skb, skb->data);
 	len = skb->len;
 
 	/*
@@ -3763,7 +3769,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 {
 	struct l2cap_chan *chan;
 	struct sock *sk = NULL;
-	u16 control;
+	u32 control;
 	u16 tx_seq;
 	int len;
 
@@ -3805,8 +3811,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		goto done;
 
 	case L2CAP_MODE_STREAMING:
-		control = get_unaligned_le16(skb->data);
-		skb_pull(skb, 2);
+		control = __get_control_pull(chan, skb, skb->data);
 		len = skb->len;
 
 		if (l2cap_check_fcs(chan, skb))
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (10 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-13 19:54   ` Gustavo Padovan
  2011-10-11 10:37 ` [PATCHv3 13/16] Bluetooth: EWS: support extended seq numbers Emeltchenko Andrei
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Recalculate length of L2CAP header based on Control field length.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   21 ++++++++++++++++++---
 1 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6a5d1d6..92b0f03 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -566,12 +566,17 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
 	struct sk_buff *skb;
 	struct l2cap_hdr *lh;
 	struct l2cap_conn *conn = chan->conn;
-	int count, hlen = L2CAP_HDR_SIZE + 2;
+	int count, hlen;
 	u8 flags;
 
 	if (chan->state != BT_CONNECTED)
 		return;
 
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		hlen = L2CAP_EXT_HDR_SIZE;
+	else
+		hlen = L2CAP_ENH_HDR_SIZE;
+
 	if (chan->fcs == L2CAP_FCS_CRC16)
 		hlen += 2;
 
@@ -1539,7 +1544,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sk_buff *skb;
-	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	int err, count, hlen;
 	struct l2cap_hdr *lh;
 
 	BT_DBG("sk %p len %d", sk, (int)len);
@@ -1547,6 +1552,11 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 	if (!conn)
 		return ERR_PTR(-ENOTCONN);
 
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		hlen = L2CAP_EXT_HDR_SIZE;
+	else
+		hlen = L2CAP_ENH_HDR_SIZE;
+
 	if (sdulen)
 		hlen += 2;
 
@@ -3105,7 +3115,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
 static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
 {
 	u16 our_fcs, rcv_fcs;
-	int hdr_size = L2CAP_HDR_SIZE + 2;
+	int hdr_size;
+
+	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+		hdr_size = L2CAP_EXT_HDR_SIZE;
+	else
+		hdr_size = L2CAP_ENH_HDR_SIZE;
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
 		skb_trim(skb, skb->len - 2);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 13/16] Bluetooth: EWS: support extended seq numbers
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (11 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes Emeltchenko Andrei
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds support for extended sequence numbers found in
extended control fields.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/bluetooth.h |    2 +-
 include/net/bluetooth/l2cap.h     |   17 ++++++++++
 net/bluetooth/l2cap_core.c        |   63 +++++++++++++++++-------------------
 3 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index e727555..fb1acb3 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -158,7 +158,7 @@ struct bt_skb_cb {
 	__u8 pkt_type;
 	__u8 incoming;
 	__u16 expect;
-	__u8 tx_seq;
+	__u16 tx_seq;
 	__u8 retries;
 	__u8 sar;
 	unsigned short channel;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 3a5f4c0..b3ae9ea 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -355,6 +355,7 @@ struct l2cap_chan {
 	__u8		fcs;
 
 	__u16		tx_win;
+	__u16		tx_win_max;
 	__u8		max_tx;
 	__u16		retrans_timeout;
 	__u16		monitor_timeout;
@@ -502,6 +503,22 @@ enum {
 		L2CAP_DEFAULT_ACK_TO);
 #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
 
+static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
+{
+	int offset;
+
+	offset = (seq1 - seq2) % (chan->tx_win_max + 1);
+	if (offset < 0)
+		offset += (chan->tx_win_max + 1);
+
+	return offset;
+}
+
+static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
+{
+	return (seq + 1) % (chan->tx_win_max + 1);
+}
+
 static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 {
 	int sub;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 92b0f03..2f1cd92 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1288,7 +1288,7 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
 
 		l2cap_do_send(chan, skb);
 
-		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
+		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
 	}
 }
 
@@ -1382,7 +1382,8 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 		__set_retrans_timer(chan);
 
 		bt_cb(skb)->tx_seq = chan->next_tx_seq;
-		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
+
+		chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
 
 		if (bt_cb(skb)->retries == 1)
 			chan->unacked_frames++;
@@ -1924,12 +1925,15 @@ static inline bool __l2cap_ews_supported(struct l2cap_chan *chan)
 static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
 {
 	if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW &&
-						__l2cap_ews_supported(chan))
+						__l2cap_ews_supported(chan)) {
 		/* use extended control field */
 		set_bit(FLAG_EXT_CTRL, &chan->flags);
-	else
+		chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
+	} else {
 		chan->tx_win = min_t(u16, chan->tx_win,
 						L2CAP_DEFAULT_TX_WINDOW);
+		chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
+	}
 }
 
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
@@ -2086,6 +2090,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 
 			set_bit(FLAG_EXT_CTRL, &chan->flags);
 			set_bit(CONF_EWS_RECV, &chan->conf_state);
+			chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
 			chan->remote_tx_win = val;
 			break;
 
@@ -3173,18 +3178,14 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
 		return 0;
 	}
 
-	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
-	if (tx_seq_offset < 0)
-		tx_seq_offset += 64;
+	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
 
 	do {
 		if (bt_cb(next_skb)->tx_seq == tx_seq)
 			return -EINVAL;
 
-		next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
-						chan->buffer_seq) % 64;
-		if (next_tx_seq_offset < 0)
-			next_tx_seq_offset += 64;
+		next_tx_seq_offset = __seq_offset(chan,
+				bt_cb(next_skb)->tx_seq, chan->buffer_seq);
 
 		if (next_tx_seq_offset > tx_seq_offset) {
 			__skb_queue_before(&chan->srej_q, next_skb, skb);
@@ -3374,9 +3375,8 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u16 tx_seq)
 			break;
 		}
 
-		chan->buffer_seq_srej =
-			(chan->buffer_seq_srej + 1) % 64;
-		tx_seq = (tx_seq + 1) % 64;
+		chan->buffer_seq_srej = __next_seq(chan, chan->buffer_seq_srej);
+		tx_seq = __next_seq(chan, tx_seq);
 	}
 }
 
@@ -3411,10 +3411,13 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
 
 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
 		new->tx_seq = chan->expected_tx_seq;
-		chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
+
+		chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
+
 		list_add_tail(&new->list, &chan->srej_l);
 	}
-	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
+
+	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
 }
 
 static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb)
@@ -3440,9 +3443,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
 	chan->expected_ack_seq = req_seq;
 	l2cap_drop_acked_frames(chan);
 
-	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;
-	if (tx_seq_offset < 0)
-		tx_seq_offset += 64;
+	tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq);
 
 	/* invalid tx_seq */
 	if (tx_seq_offset >= chan->tx_win) {
@@ -3490,10 +3491,8 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
 			l2cap_send_srejframe(chan, tx_seq);
 		}
 	} else {
-		expected_tx_seq_offset =
-			(chan->expected_tx_seq - chan->buffer_seq) % 64;
-		if (expected_tx_seq_offset < 0)
-			expected_tx_seq_offset += 64;
+		expected_tx_seq_offset = __seq_offset(chan,
+				chan->expected_tx_seq, chan->buffer_seq);
 
 		/* duplicated tx_seq */
 		if (tx_seq_offset < expected_tx_seq_offset)
@@ -3518,7 +3517,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont
 	return 0;
 
 expected:
-	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
+	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);
 
 	if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
 		bt_cb(skb)->tx_seq = tx_seq;
@@ -3528,7 +3527,8 @@ expected:
 	}
 
 	err = l2cap_reassemble_sdu(chan, skb, rx_control);
-	chan->buffer_seq = (chan->buffer_seq + 1) % 64;
+	chan->buffer_seq = __next_seq(chan, chan->buffer_seq);
+
 	if (err < 0) {
 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
 		return err;
@@ -3741,14 +3741,11 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 	}
 
 	req_seq = __get_reqseq(chan, control);
-	req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;
-	if (req_seq_offset < 0)
-		req_seq_offset += 64;
 
-	next_tx_seq_offset =
-		(chan->next_tx_seq - chan->expected_ack_seq) % 64;
-	if (next_tx_seq_offset < 0)
-		next_tx_seq_offset += 64;
+	req_seq_offset = __seq_offset(chan, req_seq, chan->expected_ack_seq);
+
+	next_tx_seq_offset = __seq_offset(chan, chan->next_tx_seq,
+						chan->expected_ack_seq);
 
 	/* check for invalid req-seq */
 	if (req_seq_offset > next_tx_seq_offset) {
@@ -3853,7 +3850,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 			/* TODO: Notify userland of missing data */
 		}
 
-		chan->expected_tx_seq = (tx_seq + 1) % 64;
+		chan->expected_tx_seq = __next_seq(chan, tx_seq);
 
 		if (l2cap_reassemble_sdu(chan, skb, control) == -EMSGSIZE)
 			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (12 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 13/16] Bluetooth: EWS: support extended seq numbers Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-13 19:55   ` Gustavo Padovan
  2011-10-11 10:37 ` [PATCHv3 15/16] Bluetooth: EWS: remove magic numbers in l2cap Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 16/16] Bluetooth: EWS: fix max_pdu calculation Emeltchenko Andrei
  15 siblings, 1 reply; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds definitins for L2CAP header sizes to be uses when calculating
payload size instead of magic numbers.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/l2cap.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b3ae9ea..ebd6392 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -164,6 +164,12 @@ struct l2cap_hdr {
 	__le16     cid;
 } __packed;
 #define L2CAP_HDR_SIZE		4
+#define L2CAP_ENH_HDR_SIZE	6
+#define L2CAP_EXT_HDR_SIZE	8
+
+#define L2CAP_FCS_SIZE		2
+#define L2CAP_SDULEN_SIZE	2
+#define L2CAP_PSMLEN_SIZE	2
 
 struct l2cap_cmd_hdr {
 	__u8       code;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 15/16] Bluetooth: EWS: remove magic numbers in l2cap
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (13 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  2011-10-11 10:37 ` [PATCHv3 16/16] Bluetooth: EWS: fix max_pdu calculation Emeltchenko Andrei
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Remove magic numbers for FCS, SDU LEN and PSM LEN
when calculating packet payload.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   46 ++++++++++++++++++++++++-------------------
 1 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2f1cd92..a703301 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -578,7 +578,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
 		hlen = L2CAP_ENH_HDR_SIZE;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
-		hlen += 2;
+		hlen += L2CAP_FCS_SIZE;
 
 	BT_DBG("chan %p, control 0x%8.8x", chan, control);
 
@@ -603,8 +603,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
 	__put_control_put(chan, control, skb);
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
-		u16 fcs = crc16(0, (u8 *)lh, count - 2);
-		put_unaligned_le16(fcs, skb_put(skb, 2));
+		u16 fcs = crc16(0, (u8 *)lh, count - L2CAP_FCS_SIZE);
+		put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
 	}
 
 	if (lmp_no_flush_capable(conn->hcon->hdev))
@@ -1282,8 +1282,10 @@ static void l2cap_streaming_send(struct l2cap_chan *chan)
 		__put_control(chan, control, skb->data + L2CAP_HDR_SIZE);
 
 		if (chan->fcs == L2CAP_FCS_CRC16) {
-			fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
-			put_unaligned_le16(fcs, skb->data + skb->len - 2);
+			fcs = crc16(0, (u8 *)skb->data,
+						skb->len - L2CAP_FCS_SIZE);
+			put_unaligned_le16(fcs,
+					skb->data + skb->len - L2CAP_FCS_SIZE);
 		}
 
 		l2cap_do_send(chan, skb);
@@ -1332,8 +1334,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq)
 	__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
-		fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
-		put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
+		fcs = crc16(0, (u8 *)tx_skb->data,
+						tx_skb->len - L2CAP_FCS_SIZE);
+		put_unaligned_le16(fcs,
+				tx_skb->data + tx_skb->len - L2CAP_FCS_SIZE);
 	}
 
 	l2cap_do_send(chan, tx_skb);
@@ -1373,8 +1377,10 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
 		__put_control(chan, control, tx_skb->data + L2CAP_HDR_SIZE);
 
 		if (chan->fcs == L2CAP_FCS_CRC16) {
-			fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
-			put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
+			fcs = crc16(0, (u8 *)skb->data,
+						tx_skb->len - L2CAP_FCS_SIZE);
+			put_unaligned_le16(fcs, skb->data +
+						tx_skb->len - L2CAP_FCS_SIZE);
 		}
 
 		l2cap_do_send(chan, tx_skb);
@@ -1484,7 +1490,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct
 	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct sk_buff *skb;
-	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
 	struct l2cap_hdr *lh;
 
 	BT_DBG("sk %p len %d", sk, (int)len);
@@ -1559,10 +1565,10 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 		hlen = L2CAP_ENH_HDR_SIZE;
 
 	if (sdulen)
-		hlen += 2;
+		hlen += L2CAP_SDULEN_SIZE;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
-		hlen += 2;
+		hlen += L2CAP_FCS_SIZE;
 
 	count = min_t(unsigned int, (conn->mtu - hlen), len);
 	skb = bt_skb_send_alloc(sk, count + hlen,
@@ -1578,7 +1584,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 	__put_control_put(chan, control, skb);
 
 	if (sdulen)
-		put_unaligned_le16(sdulen, skb_put(skb, 2));
+		put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
 
 	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
 	if (unlikely(err < 0)) {
@@ -1587,7 +1593,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
 	}
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
-		put_unaligned_le16(0, skb_put(skb, 2));
+		put_unaligned_le16(0, skb_put(skb, L2CAP_FCS_SIZE));
 
 	bt_cb(skb)->retries = 0;
 	return skb;
@@ -3128,7 +3134,7 @@ static int l2cap_check_fcs(struct l2cap_chan *chan,  struct sk_buff *skb)
 		hdr_size = L2CAP_ENH_HDR_SIZE;
 
 	if (chan->fcs == L2CAP_FCS_CRC16) {
-		skb_trim(skb, skb->len - 2);
+		skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
 		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
 		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
 
@@ -3238,7 +3244,7 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3
 			break;
 
 		chan->sdu_len = get_unaligned_le16(skb->data);
-		skb_pull(skb, 2);
+		skb_pull(skb, L2CAP_SDULEN_SIZE);
 
 		if (chan->sdu_len > chan->imtu) {
 			err = -EMSGSIZE;
@@ -3730,10 +3736,10 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
 		goto drop;
 
 	if (__is_sar_start(chan, control) && !__is_sframe(chan, control))
-		len -= 2;
+		len -= L2CAP_SDULEN_SIZE;
 
 	if (chan->fcs == L2CAP_FCS_CRC16)
-		len -= 2;
+		len -= L2CAP_FCS_SIZE;
 
 	if (len > chan->mps) {
 		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
@@ -3830,10 +3836,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 			goto drop;
 
 		if (__is_sar_start(chan, control))
-			len -= 2;
+			len -= L2CAP_SDULEN_SIZE;
 
 		if (chan->fcs == L2CAP_FCS_CRC16)
-			len -= 2;
+			len -= L2CAP_FCS_SIZE;
 
 		if (len > chan->mps || len < 0 || __is_sframe(chan, control))
 			goto drop;
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCHv3 16/16] Bluetooth: EWS: fix max_pdu calculation
  2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
                   ` (14 preceding siblings ...)
  2011-10-11 10:37 ` [PATCHv3 15/16] Bluetooth: EWS: remove magic numbers in l2cap Emeltchenko Andrei
@ 2011-10-11 10:37 ` Emeltchenko Andrei
  15 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-11 10:37 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Fix max_pdu_size calculationin for RFC. Change magic number to human readable
defines.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   42 ++++++++++++++++++++++++++++--------------
 1 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a703301..d418ddb 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1947,6 +1947,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
 	struct l2cap_conf_req *req = data;
 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
 	void *ptr = req->data;
+	u16 size;
 
 	BT_DBG("chan %p", chan);
 
@@ -1991,9 +1992,12 @@ done:
 		rfc.max_transmit    = chan->max_tx;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
-		if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
-			rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
+
+		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
+						L2CAP_EXT_HDR_SIZE -
+						L2CAP_SDULEN_SIZE -
+						L2CAP_FCS_SIZE);
+		rfc.max_pdu_size = cpu_to_le16(size);
 
 		l2cap_txwin_setup(chan);
 
@@ -2023,9 +2027,12 @@ done:
 		rfc.max_transmit    = 0;
 		rfc.retrans_timeout = 0;
 		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
-		if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
-			rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
+
+		size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu -
+						L2CAP_EXT_HDR_SIZE -
+						L2CAP_SDULEN_SIZE -
+						L2CAP_FCS_SIZE);
+		rfc.max_pdu_size = cpu_to_le16(size);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
 							(unsigned long) &rfc);
@@ -2058,6 +2065,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
 	u16 mtu = L2CAP_DEFAULT_MTU;
 	u16 result = L2CAP_CONF_SUCCESS;
+	u16 size;
 
 	BT_DBG("chan %p", chan);
 
@@ -2167,10 +2175,13 @@ done:
 
 			chan->remote_max_tx = rfc.max_transmit;
 
-			if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
-				rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
-
-			chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
+						chan->conn->mtu -
+						L2CAP_EXT_HDR_SIZE -
+						L2CAP_SDULEN_SIZE -
+						L2CAP_FCS_SIZE);
+			rfc.max_pdu_size = cpu_to_le16(size);
+			chan->remote_mps = size;
 
 			rfc.retrans_timeout =
 				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
@@ -2185,10 +2196,13 @@ done:
 			break;
 
 		case L2CAP_MODE_STREAMING:
-			if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
-				rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
-
-			chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+			size = min_t(u16, le16_to_cpu(rfc.max_pdu_size),
+						chan->conn->mtu -
+						L2CAP_EXT_HDR_SIZE -
+						L2CAP_SDULEN_SIZE -
+						L2CAP_FCS_SIZE);
+			rfc.max_pdu_size = cpu_to_le16(size);
+			chan->remote_mps = size;
 
 			set_bit(CONF_MODE_DONE, &chan->conf_state);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit
  2011-10-11 10:37 ` [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit Emeltchenko Andrei
@ 2011-10-13 19:47   ` Gustavo Padovan
  0 siblings, 0 replies; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-13 19:47 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:50 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Handle POLL (P) bit in L2CAP ERTM using information about control field type.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/l2cap.h |   16 ++++++++++++++++
>  net/bluetooth/l2cap_core.c    |   14 +++++++-------
>  2 files changed, 23 insertions(+), 7 deletions(-)

Patches up to this one were applied. Thanks for doing this work.

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields
  2011-10-11 10:37 ` [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields Emeltchenko Andrei
@ 2011-10-13 19:49   ` Gustavo Padovan
  2011-10-14 10:56     ` Emeltchenko Andrei
  0 siblings, 1 reply; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-13 19:49 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:51 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> There are three different Control Field formats: the Standard Control
> Field, the Enhanced Control Field, and the Extended Control Field.
> Patch adds function to handle all those fields seamlessly.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/l2cap.h |   43 +++++++++++++++++++
>  net/bluetooth/l2cap_core.c    |   93 +++++++++++++++++++++-------------------
>  2 files changed, 92 insertions(+), 44 deletions(-)
> 
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 67a2fdb..3a5f4c0 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -27,6 +27,8 @@
>  #ifndef __L2CAP_H
>  #define __L2CAP_H
>  
> +#include <asm/unaligned.h>
> +
>  /* L2CAP defaults */
>  #define L2CAP_DEFAULT_MTU		672
>  #define L2CAP_DEFAULT_MIN_MTU		48
> @@ -643,6 +645,47 @@ static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
>  	else
>  		return ctrl & L2CAP_CTRL_POLL;
>  }
> +
> +static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
> +{
> +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> +		return get_unaligned_le32(p);
> +	else
> +		return get_unaligned_le16(p);
> +}
> +
> +static inline __u32 __get_control_pull(struct l2cap_chan *chan,
> +		struct sk_buff *skb, void *p)
> +{
> +	__u32 ctrl;
> +
> +	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
> +		ctrl = get_unaligned_le32(p);
> +		skb_pull(skb, 4);
> +	} else {
> +		ctrl = get_unaligned_le16(p);
> +		skb_pull(skb, 2);
> +	}


I prefer not hide the skb_pull inside another function.

> +
> +	return ctrl;
> +}
> +
> +static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
> +{
> +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> +		return put_unaligned_le32(control, p);
> +	else
> +		return put_unaligned_le16(control, p);
> +}
> +
> +static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
> +{
> +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> +		return put_unaligned_le32(control, skb_put(p, 4));
> +	else
> +		return put_unaligned_le16(control, skb_put(p, 2));
> +}


get ride of this, you still can do __put_control(chan, control, skb_put())

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size
  2011-10-11 10:37 ` [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size Emeltchenko Andrei
@ 2011-10-13 19:54   ` Gustavo Padovan
  0 siblings, 0 replies; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-13 19:54 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:52 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Recalculate length of L2CAP header based on Control field length.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  net/bluetooth/l2cap_core.c |   21 ++++++++++++++++++---
>  1 files changed, 18 insertions(+), 3 deletions(-)

Applied, thanks.

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes
  2011-10-11 10:37 ` [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes Emeltchenko Andrei
@ 2011-10-13 19:55   ` Gustavo Padovan
  2011-10-14 11:15     ` Emeltchenko Andrei
  0 siblings, 1 reply; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-13 19:55 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:54 +0300]:

> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Adds definitins for L2CAP header sizes to be uses when calculating
> payload size instead of magic numbers.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> ---
>  include/net/bluetooth/l2cap.h |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)

Applied, Thanks. Please fix patch 11 and rebase the others so I can apply
everything.

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields
  2011-10-13 19:49   ` Gustavo Padovan
@ 2011-10-14 10:56     ` Emeltchenko Andrei
  2011-10-14 18:09       ` Gustavo Padovan
  0 siblings, 1 reply; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-14 10:56 UTC (permalink / raw)
  To: linux-bluetooth

Hi Gustavo,

On Thu, Oct 13, 2011 at 04:49:25PM -0300, Gustavo Padovan wrote:
> * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:51 +0300]:
> 
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > 
> > There are three different Control Field formats: the Standard Control
> > Field, the Enhanced Control Field, and the Extended Control Field.
> > Patch adds function to handle all those fields seamlessly.
> > 
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > ---
> >  include/net/bluetooth/l2cap.h |   43 +++++++++++++++++++
> >  net/bluetooth/l2cap_core.c    |   93 +++++++++++++++++++++-------------------
> >  2 files changed, 92 insertions(+), 44 deletions(-)
> > 
> > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> > index 67a2fdb..3a5f4c0 100644
> > --- a/include/net/bluetooth/l2cap.h
> > +++ b/include/net/bluetooth/l2cap.h
> > @@ -27,6 +27,8 @@
> >  #ifndef __L2CAP_H
> >  #define __L2CAP_H
> >  
> > +#include <asm/unaligned.h>
> > +
> >  /* L2CAP defaults */
> >  #define L2CAP_DEFAULT_MTU		672
> >  #define L2CAP_DEFAULT_MIN_MTU		48
> > @@ -643,6 +645,47 @@ static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
> >  	else
> >  		return ctrl & L2CAP_CTRL_POLL;
> >  }
> > +
> > +static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
> > +{
> > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > +		return get_unaligned_le32(p);
> > +	else
> > +		return get_unaligned_le16(p);
> > +}
> > +
> > +static inline __u32 __get_control_pull(struct l2cap_chan *chan,
> > +		struct sk_buff *skb, void *p)
> > +{
> > +	__u32 ctrl;
> > +
> > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
> > +		ctrl = get_unaligned_le32(p);
> > +		skb_pull(skb, 4);
> > +	} else {
> > +		ctrl = get_unaligned_le16(p);
> > +		skb_pull(skb, 2);
> > +	}
> 
> 
> I prefer not hide the skb_pull inside another function.

OK, I will change it to something like:

<------8<----------------------------------------------------------------
|  @@ -4005,7 +4009,8 @@ static int l2cap_ertm_data_rcv(struct sock *sk,
|  struct sk_buff *skb)
|          u16 req_seq;
|          int len, next_tx_seq_offset, req_seq_offset;
|
|  -       control = __get_control_pull(chan, skb, skb->data);
|  +       control = __get_control(chan, skb->data);
|  +       skb_pull(skb, __get_ctrl_size(chan));
|          len = skb->len;
|
|          /*
|
<------8<----------------------------------------------------------------


> > +
> > +	return ctrl;
> > +}
> > +
> > +static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
> > +{
> > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > +		return put_unaligned_le32(control, p);
> > +	else
> > +		return put_unaligned_le16(control, p);
> > +}
> > +
> > +static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
> > +{
> > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > +		return put_unaligned_le32(control, skb_put(p, 4));
> > +	else
> > +		return put_unaligned_le16(control, skb_put(p, 2));
> > +}
> 
> 
> get ride of this, you still can do __put_control(chan, control,
> skb_put())
the second argument in skb_put changes so I cannot use proposed way.

what about change to code below:

<------8<--------------------------------------------------------
|  @@ -1586,6 +1588,7 @@ static struct sk_buff
|  *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
|          struct sk_buff *skb;
|          int err, count, hlen;
|          struct l2cap_hdr *lh;
|  +       unsigned char *data;
|
|          BT_DBG("sk %p len %d", sk, (int)len);
|
|  @@ -1614,7 +1617,8 @@ static struct sk_buff
|  *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
|          lh->cid = cpu_to_le16(chan->dcid);
|          lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
|
|  -       __put_control_put(chan, control, skb);
|  +       data = skb_put(skb, __get_ctrl_size(chan));
|  +       __put_control(chan, control, data);
|
|          if (sdulen)
|                  put_unaligned_le16(sdulen, skb_put(skb,
|  L2CAP_SDULEN_SIZE));
|
<------8<--------------------------------------------------------

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes
  2011-10-13 19:55   ` Gustavo Padovan
@ 2011-10-14 11:15     ` Emeltchenko Andrei
  0 siblings, 0 replies; 25+ messages in thread
From: Emeltchenko Andrei @ 2011-10-14 11:15 UTC (permalink / raw)
  To: linux-bluetooth

Hi Gustavo,

On Thu, Oct 13, 2011 at 04:55:35PM -0300, Gustavo Padovan wrote:
> Hi Andrei,
> 
> * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:54 +0300]:
> 
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > 
> > Adds definitins for L2CAP header sizes to be uses when calculating
> > payload size instead of magic numbers.
> > 
> > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > ---
> >  include/net/bluetooth/l2cap.h |    6 ++++++
> >  1 files changed, 6 insertions(+), 0 deletions(-)
> 
> Applied, Thanks. Please fix patch 11 and rebase the others so I can apply
> everything.

Sorry for noticing it late, could you rearrange that patch so that it
comes before "Bluetooth: EWS: recalculate L2CAP header size" 
(PATCHv3 12/16)

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields
  2011-10-14 10:56     ` Emeltchenko Andrei
@ 2011-10-14 18:09       ` Gustavo Padovan
  2011-10-14 18:19         ` Gustavo Padovan
  0 siblings, 1 reply; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-14 18:09 UTC (permalink / raw)
  To: Emeltchenko Andrei, linux-bluetooth

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-14 13:56:03 +0300]:

> Hi Gustavo,
> 
> On Thu, Oct 13, 2011 at 04:49:25PM -0300, Gustavo Padovan wrote:
> > * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:51 +0300]:
> > 
> > > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > > 
> > > There are three different Control Field formats: the Standard Control
> > > Field, the Enhanced Control Field, and the Extended Control Field.
> > > Patch adds function to handle all those fields seamlessly.
> > > 
> > > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > > ---
> > >  include/net/bluetooth/l2cap.h |   43 +++++++++++++++++++
> > >  net/bluetooth/l2cap_core.c    |   93 +++++++++++++++++++++-------------------
> > >  2 files changed, 92 insertions(+), 44 deletions(-)
> > > 
> > > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> > > index 67a2fdb..3a5f4c0 100644
> > > --- a/include/net/bluetooth/l2cap.h
> > > +++ b/include/net/bluetooth/l2cap.h
> > > @@ -27,6 +27,8 @@
> > >  #ifndef __L2CAP_H
> > >  #define __L2CAP_H
> > >  
> > > +#include <asm/unaligned.h>
> > > +
> > >  /* L2CAP defaults */
> > >  #define L2CAP_DEFAULT_MTU		672
> > >  #define L2CAP_DEFAULT_MIN_MTU		48
> > > @@ -643,6 +645,47 @@ static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
> > >  	else
> > >  		return ctrl & L2CAP_CTRL_POLL;
> > >  }
> > > +
> > > +static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
> > > +{
> > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > +		return get_unaligned_le32(p);
> > > +	else
> > > +		return get_unaligned_le16(p);
> > > +}
> > > +
> > > +static inline __u32 __get_control_pull(struct l2cap_chan *chan,
> > > +		struct sk_buff *skb, void *p)
> > > +{
> > > +	__u32 ctrl;
> > > +
> > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
> > > +		ctrl = get_unaligned_le32(p);
> > > +		skb_pull(skb, 4);
> > > +	} else {
> > > +		ctrl = get_unaligned_le16(p);
> > > +		skb_pull(skb, 2);
> > > +	}
> > 
> > 
> > I prefer not hide the skb_pull inside another function.
> 
> OK, I will change it to something like:
> 
> <------8<----------------------------------------------------------------
> |  @@ -4005,7 +4009,8 @@ static int l2cap_ertm_data_rcv(struct sock *sk,
> |  struct sk_buff *skb)
> |          u16 req_seq;
> |          int len, next_tx_seq_offset, req_seq_offset;
> |
> |  -       control = __get_control_pull(chan, skb, skb->data);
> |  +       control = __get_control(chan, skb->data);
> |  +       skb_pull(skb, __get_ctrl_size(chan));
> |          len = skb->len;
> |
> |          /*
> |
> <------8<----------------------------------------------------------------
> 
> 
> > > +
> > > +	return ctrl;
> > > +}
> > > +
> > > +static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
> > > +{
> > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > +		return put_unaligned_le32(control, p);
> > > +	else
> > > +		return put_unaligned_le16(control, p);
> > > +}
> > > +
> > > +static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
> > > +{
> > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > +		return put_unaligned_le32(control, skb_put(p, 4));
> > > +	else
> > > +		return put_unaligned_le16(control, skb_put(p, 2));
> > > +}
> > 
> > 
> > get ride of this, you still can do __put_control(chan, control,
> > skb_put())
> the second argument in skb_put changes so I cannot use proposed way.

Why not? 

You just call __put_control(chan, control, skb_put(skb, N));

This pass exactly what you want to __put_control(). Do you agree?

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields
  2011-10-14 18:09       ` Gustavo Padovan
@ 2011-10-14 18:19         ` Gustavo Padovan
  0 siblings, 0 replies; 25+ messages in thread
From: Gustavo Padovan @ 2011-10-14 18:19 UTC (permalink / raw)
  To: Emeltchenko Andrei, linux-bluetooth

* Gustavo Padovan <padovan@profusion.mobi> [2011-10-14 15:09:15 -0300]:

> Hi Andrei,
> 
> * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-14 13:56:03 +0300]:
> 
> > Hi Gustavo,
> > 
> > On Thu, Oct 13, 2011 at 04:49:25PM -0300, Gustavo Padovan wrote:
> > > * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-10-11 13:37:51 +0300]:
> > > 
> > > > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > > > 
> > > > There are three different Control Field formats: the Standard Control
> > > > Field, the Enhanced Control Field, and the Extended Control Field.
> > > > Patch adds function to handle all those fields seamlessly.
> > > > 
> > > > Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > > > ---
> > > >  include/net/bluetooth/l2cap.h |   43 +++++++++++++++++++
> > > >  net/bluetooth/l2cap_core.c    |   93 +++++++++++++++++++++-------------------
> > > >  2 files changed, 92 insertions(+), 44 deletions(-)
> > > > 
> > > > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> > > > index 67a2fdb..3a5f4c0 100644
> > > > --- a/include/net/bluetooth/l2cap.h
> > > > +++ b/include/net/bluetooth/l2cap.h
> > > > @@ -27,6 +27,8 @@
> > > >  #ifndef __L2CAP_H
> > > >  #define __L2CAP_H
> > > >  
> > > > +#include <asm/unaligned.h>
> > > > +
> > > >  /* L2CAP defaults */
> > > >  #define L2CAP_DEFAULT_MTU		672
> > > >  #define L2CAP_DEFAULT_MIN_MTU		48
> > > > @@ -643,6 +645,47 @@ static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl)
> > > >  	else
> > > >  		return ctrl & L2CAP_CTRL_POLL;
> > > >  }
> > > > +
> > > > +static inline __u32 __get_control(struct l2cap_chan *chan, void *p)
> > > > +{
> > > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > > +		return get_unaligned_le32(p);
> > > > +	else
> > > > +		return get_unaligned_le16(p);
> > > > +}
> > > > +
> > > > +static inline __u32 __get_control_pull(struct l2cap_chan *chan,
> > > > +		struct sk_buff *skb, void *p)
> > > > +{
> > > > +	__u32 ctrl;
> > > > +
> > > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
> > > > +		ctrl = get_unaligned_le32(p);
> > > > +		skb_pull(skb, 4);
> > > > +	} else {
> > > > +		ctrl = get_unaligned_le16(p);
> > > > +		skb_pull(skb, 2);
> > > > +	}
> > > 
> > > 
> > > I prefer not hide the skb_pull inside another function.
> > 
> > OK, I will change it to something like:
> > 
> > <------8<----------------------------------------------------------------
> > |  @@ -4005,7 +4009,8 @@ static int l2cap_ertm_data_rcv(struct sock *sk,
> > |  struct sk_buff *skb)
> > |          u16 req_seq;
> > |          int len, next_tx_seq_offset, req_seq_offset;
> > |
> > |  -       control = __get_control_pull(chan, skb, skb->data);
> > |  +       control = __get_control(chan, skb->data);
> > |  +       skb_pull(skb, __get_ctrl_size(chan));
> > |          len = skb->len;
> > |
> > |          /*
> > |
> > <------8<----------------------------------------------------------------
> > 
> > 
> > > > +
> > > > +	return ctrl;
> > > > +}
> > > > +
> > > > +static inline void __put_control(struct l2cap_chan *chan, __u32 control, void *p)
> > > > +{
> > > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > > +		return put_unaligned_le32(control, p);
> > > > +	else
> > > > +		return put_unaligned_le16(control, p);
> > > > +}
> > > > +
> > > > +static inline void __put_control_put(struct l2cap_chan *chan, __u32 control, void *p)
> > > > +{
> > > > +	if (test_bit(FLAG_EXT_CTRL, &chan->flags))
> > > > +		return put_unaligned_le32(control, skb_put(p, 4));
> > > > +	else
> > > > +		return put_unaligned_le16(control, skb_put(p, 2));
> > > > +}
> > > 
> > > 
> > > get ride of this, you still can do __put_control(chan, control,
> > > skb_put())
> > the second argument in skb_put changes so I cannot use proposed way.
> 
> Why not? 
> 
> You just call __put_control(chan, control, skb_put(skb, N));

Actually it is __get_ctrl_size() instead of N here, and just rename it to
__ctrl_size() only.

	Gustavo

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2011-10-14 18:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-11 10:37 [PATCHv3 00/16] EWS: extended window size and extended control field support Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 01/16] Bluetooth: clean up spaces in L2CAP header Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 02/16] Bluetooth: EWS: extended window size option support Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 03/16] Bluetooth: EWS: adds ext control field bit mask Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 04/16] Bluetooth: EWS: rewrite handling Supervisory (S) bits Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 05/16] Bluetooth: EWS: rewrite handling SAR bits Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 06/16] Bluetooth: EWS: rewrite reqseq calculation Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 07/16] Bluetooth: EWS: rewrite L2CAP ERTM txseq calculation Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 08/16] Bluetooth: EWS: rewrite check frame type function Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 09/16] Bluetooth: EWS: rewrite handling FINAL (F) bit Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 10/16] Bluetooth: EWS: rewrite handling POLL (P) bit Emeltchenko Andrei
2011-10-13 19:47   ` Gustavo Padovan
2011-10-11 10:37 ` [PATCHv3 11/16] Bluetooth: EWS: handling different Control fields Emeltchenko Andrei
2011-10-13 19:49   ` Gustavo Padovan
2011-10-14 10:56     ` Emeltchenko Andrei
2011-10-14 18:09       ` Gustavo Padovan
2011-10-14 18:19         ` Gustavo Padovan
2011-10-11 10:37 ` [PATCHv3 12/16] Bluetooth: EWS: recalculate L2CAP header size Emeltchenko Andrei
2011-10-13 19:54   ` Gustavo Padovan
2011-10-11 10:37 ` [PATCHv3 13/16] Bluetooth: EWS: support extended seq numbers Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 14/16] Bluetooth: EWS: define L2CAP header sizes Emeltchenko Andrei
2011-10-13 19:55   ` Gustavo Padovan
2011-10-14 11:15     ` Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 15/16] Bluetooth: EWS: remove magic numbers in l2cap Emeltchenko Andrei
2011-10-11 10:37 ` [PATCHv3 16/16] Bluetooth: EWS: fix max_pdu calculation Emeltchenko Andrei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.