Linux bluetooth development
 help / color / mirror / Atom feed
* Can't turn off bluetooth with discoverable mode on Lucid
From: Chao Deng @ 2010-03-23  9:41 UTC (permalink / raw)
  To: linux-bluetooth

When I use "hciconfig" to turn off Bluetooth, I meet a problem that it
can't be turned off correctly when discoverable. I need to run
"hciconfig hci0 down" twice to turn off it, following is the log
information.
[LOG]
root@ubuntu-laptop:/home/ubuntu# hciconfig
hci0: Type: SDIO
        BD Address: 00:24:23:10:97:A3 ACL MTU: 1021:7 SCO MTU: 240:3
        UP RUNNING PSCAN ISCAN
        RX bytes:2324 acl:0 sco:0 events:71 errors:0
        TX bytes:2746 acl:0 sco:0 commands:71 errors:0

root@ubuntu-laptop:/home/ubuntu# hciconfig hci0 down
root@ubuntu-laptop:/home/ubuntu# hciconfig
hci0: Type: SDIO
        BD Address: 00:24:23:10:97:A3 ACL MTU: 1021:7 SCO MTU: 240:3
        UP RUNNING PSCAN
        RX bytes:3467 acl:0 sco:0 events:105 errors:0
        TX bytes:4227 acl:0 sco:0 commands:105 errors:0

root@ubuntu-laptop:/home/ubuntu# hciconfig hci0 down
root@ubuntu-laptop:/home/ubuntu# hciconfig
hci0: Type: SDIO
        BD Address: 00:24:23:10:97:A3 ACL MTU: 1021:7 SCO MTU: 240:3
        DOWN
        RX bytes:3477 acl:0 sco:0 events:106 errors:0
        TX bytes:4234 acl:0 sco:0 commands:106 errors:0

[/LOG]
At the first time of "hciconfig hci0 down", the bluetooth adapter is
turned off and then turned on again (who turn on it?). The mode is
changed from "UP RUNNING PSCAN ISCAN" to "DOWN" (I can't capture this
change), and then from "DOWN" to "UP RUNNING PSCAN" (This is what we
see after run this command). You can see the time stamp in the log
file (syslog)
At the second time, the bluetooth adapter is turned off, mode is
changed to "DOWN".

This is part of the /var/log/syslog, you can see the state of "HCI dev 0"
[LOG]
Jul 29 08:54:01 ubuntu-laptop bluetoothd[1061]: Bluetooth daemon 4.60
Jul 29 08:54:01 ubuntu-laptop bluetoothd[1062]: Starting SDP server
Jul 29 08:54:01 ubuntu-laptop bluetoothd[1062]: Starting experimental
netlink support
Jul 29 08:54:01 ubuntu-laptop bluetoothd[1062]: Failed to find
Bluetooth netlink family
Jul 29 08:54:01 ubuntu-laptop bluetoothd[1062]: Failed to init netlink plugin
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Can't create GN bridge
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Unable to start SCO
server socket
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Failed to init audio plugin
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: HCI dev 0 registered
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Failed to open RFKILL
control device
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: accept: Socket
operation on non-socket (88)
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: HCI dev 0 up
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Starting security manager 0
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Parsing
/etc/bluetooth/serial.conf failed: No such file or directory
Jul 29 08:54:02 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been enabled
Jul 29 08:54:15 ubuntu-laptop AptDaemon: INFO: Initializing daemon
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: HCI dev 0 down
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been disabled
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: Stopping security manager 0
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: HCI dev 0 up
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: Starting security manager 0
Jul 29 08:54:33 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been enabled
Jul 29 08:59:16 ubuntu-laptop AptDaemon: INFO: Quiting due to inactivity
Jul 29 08:59:16 ubuntu-laptop AptDaemon: INFO: Shutdown was requested
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: HCI dev 0 down
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been disabled
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: Stopping security manager 0
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: HCI dev 0 up
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: Starting security manager 0
Jul 29 09:06:29 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been enabled
Jul 29 09:06:41 ubuntu-laptop bluetoothd[1062]: HCI dev 0 down
Jul 29 09:06:41 ubuntu-laptop bluetoothd[1062]: Adapter
/org/bluez/1061/hci0 has been disabled
Jul 29 09:06:41 ubuntu-laptop bluetoothd[1062]: Stopping security manager 0

[/LOG]

The release of Ubuntu that I use is Ubuntu Lucid.
    root@ubuntu-laptop:/home/ubuntu# lsb_release -rd
    Description: Ubuntu lucid (development branch)
    Release: 10.04
And the bluez version is 4.60-0ubuntu5.
The kernel version is 2.6.32.9.
The test platform that I use is Dove (ARM platform), and the Bluetooth
Adapter is Marvell SD8688.

By the way, I have test it on Karmic with the same kernel and driver,
it's workable. I also try to downgrade the Bluez version from 4.60 to
4.51(used in Karmic release), but it doesn't help, the problem still
exists.
Then, I kill the process "bluetoothd" and try it again, I can run
"hciconfig hci0 down" only once to turn off it (from "UP RUNNING PSCAN
ISCAN" to "DOWN"). So maybe something happens and lets "bluetoothd" to
turn on the adapter, how to trace it?

Do anyone else have the same problem like me? Or could you share some
methods to debug it?

^ permalink raw reply

* [PATCH 00/19] Patches for eL2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses

Hi,

In the following e-mails there is a patch set for the Enhanced Retransmission Mode. Part of them are new features implementation and the other part is bug fixes.

Gustavo F. Padovan (19):
      Bluetooth: Implement 'Send IorRRorRNR' event
      Bluetooth: Support case with F bit set under WAIT_F state.
      Bluetooth: Fix memory leak of S-frames into L2CAP
      Bluetooth: Check the minimum {I,S}-frame size into L2CAP
      Bluetooth: Check if SDU size is greater than MTU on L2CAP
      Bluetooth: Fix expected_tx_seq calculation on L2CAP
      Bluetooth: Implement SendAck() Action on ERTM.
      Bluetooth: Move set of P-bit to l2cap_send_sframe()
      Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM
      Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro
      Bluetooth: Fix ACL MTU issue
      Bluetooth: Split l2cap_data_channel_sframe()
      Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP
      Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe()
      Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP
      Bluetooth: Finish implementation for Rec RR (P=1) on ERTM
      Bluetooth: Ignore I-frames with a duplicated txSeq
      Bluetooth: Add timer to Acknowledge I-frames
      Bluetooth: Move specific Basic Mode code to the right place


 include/net/bluetooth/l2cap.h |   24 ++-
 net/bluetooth/l2cap.c         |  382 +++++++++++++++++++++++++++++------------
 2 files changed, 286 insertions(+), 120 deletions(-)

^ permalink raw reply

* [PATCH 01/19] Bluetooth: Implement 'Send IorRRorRNR' event
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-1-git-send-email-padovan@profusion.mobi>

After receive a RR with P bit set ERTM shall use this funcion to choose
what type of frame to reply with F bit = 1.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |   20 ++++++++++--------
 net/bluetooth/l2cap.c         |   44 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 17a689f..d9c20c3 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -320,7 +320,7 @@ struct l2cap_pinfo {
 	__u8		conf_req[64];
 	__u8		conf_len;
 	__u8		conf_state;
-	__u8		conn_state;
+	__u16		conn_state;
 
 	__u8		next_tx_seq;
 	__u8		expected_ack_seq;
@@ -328,6 +328,7 @@ struct l2cap_pinfo {
 	__u8		buffer_seq;
 	__u8		buffer_seq_srej;
 	__u8		srej_save_reqseq;
+	__u8		frames_sent;
 	__u8		unacked_frames;
 	__u8		retry_count;
 	__u8		num_to_ack;
@@ -367,14 +368,15 @@ struct l2cap_pinfo {
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
-#define L2CAP_CONN_SAR_SDU         0x01
-#define L2CAP_CONN_SREJ_SENT       0x02
-#define L2CAP_CONN_WAIT_F          0x04
-#define L2CAP_CONN_SREJ_ACT        0x08
-#define L2CAP_CONN_SEND_PBIT       0x10
-#define L2CAP_CONN_REMOTE_BUSY     0x20
-#define L2CAP_CONN_LOCAL_BUSY      0x40
-#define L2CAP_CONN_REJ_ACT         0x80
+#define L2CAP_CONN_SAR_SDU         0x0001
+#define L2CAP_CONN_SREJ_SENT       0x0002
+#define L2CAP_CONN_WAIT_F          0x0004
+#define L2CAP_CONN_SREJ_ACT        0x0008
+#define L2CAP_CONN_SEND_PBIT       0x0010
+#define L2CAP_CONN_REMOTE_BUSY     0x0020
+#define L2CAP_CONN_LOCAL_BUSY      0x0040
+#define L2CAP_CONN_REJ_ACT         0x0080
+#define L2CAP_CONN_SEND_FBIT       0x0100
 
 #define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
 		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 7794a2e..18328a4 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1382,6 +1382,10 @@ static int l2cap_ertm_send(struct sock *sk)
 		bt_cb(skb)->retries++;
 
 		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+			control |= L2CAP_CTRL_FINAL;
+			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+		}
 		control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
 				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1403,6 +1407,7 @@ static int l2cap_ertm_send(struct sock *sk)
 		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
 
 		pi->unacked_frames++;
+		pi->frames_sent++;
 
 		if (skb_queue_is_last(TX_QUEUE(sk), skb))
 			sk->sk_send_head = NULL;
@@ -2186,6 +2191,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
 	l2cap_pi(sk)->unacked_frames = 0;
 	l2cap_pi(sk)->buffer_seq = 0;
 	l2cap_pi(sk)->num_to_ack = 0;
+	l2cap_pi(sk)->frames_sent = 0;
 
 	setup_timer(&l2cap_pi(sk)->retrans_timer,
 			l2cap_retrans_timeout, (unsigned long) sk);
@@ -3139,6 +3145,39 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi,  struct sk_buff *skb)
 	return 0;
 }
 
+static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control = 0;
+
+	pi->frames_sent = 0;
+	pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+
+	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		control |= L2CAP_SUPER_RCV_NOT_READY | L2CAP_CTRL_FINAL;
+		l2cap_send_sframe(pi, control);
+		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+
+	}
+
+	if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
+		__mod_retrans_timer();
+
+	l2cap_ertm_send(sk);
+
+	if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+			pi->frames_sent == 0) {
+		control |= L2CAP_SUPER_RCV_READY;
+		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+			control |= L2CAP_CTRL_FINAL;
+			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+		}
+		l2cap_send_sframe(pi, control);
+	}
+}
+
 static void l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
 {
 	struct sk_buff *next_skb;
@@ -3409,10 +3448,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
 	case L2CAP_SUPER_RCV_READY:
 		if (rx_control & L2CAP_CTRL_POLL) {
-			u16 control = L2CAP_CTRL_FINAL;
-			control |= L2CAP_SUPER_RCV_READY |
-				(pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT);
-			l2cap_send_sframe(l2cap_pi(sk), control);
+			l2cap_send_i_or_rr_or_rnr(sk);
 			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
 		} else if (rx_control & L2CAP_CTRL_FINAL) {
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 02/19] Bluetooth: Support case with F bit set under WAIT_F state.
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-2-git-send-email-padovan@profusion.mobi>

On receipt of a F=1 under WAIT_F state ERTM shall stop monitor timer and
start retransmission timer (if there are unacked frames).

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   22 ++++++++++++++--------
 1 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 18328a4..ab3f0c4 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3356,6 +3356,13 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 
 	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
+	if (L2CAP_CTRL_FINAL & rx_control) {
+		del_timer(&pi->monitor_timer);
+		if (pi->unacked_frames > 0)
+			__mod_retrans_timer();
+		pi->conn_state &= ~L2CAP_CONN_WAIT_F;
+	}
+
 	pi->expected_ack_seq = req_seq;
 	l2cap_drop_acked_frames(sk);
 
@@ -3445,6 +3452,13 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 
 	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
 
+	if (L2CAP_CTRL_FINAL & rx_control) {
+		del_timer(&pi->monitor_timer);
+		if (pi->unacked_frames > 0)
+			__mod_retrans_timer();
+		pi->conn_state &= ~L2CAP_CONN_WAIT_F;
+	}
+
 	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
 	case L2CAP_SUPER_RCV_READY:
 		if (rx_control & L2CAP_CTRL_POLL) {
@@ -3464,14 +3478,6 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 				l2cap_ertm_send(sk);
 			}
 
-			if (!(pi->conn_state & L2CAP_CONN_WAIT_F))
-				break;
-
-			pi->conn_state &= ~L2CAP_CONN_WAIT_F;
-			del_timer(&pi->monitor_timer);
-
-			if (pi->unacked_frames > 0)
-				__mod_retrans_timer();
 		} else {
 			pi->expected_ack_seq = tx_seq;
 			l2cap_drop_acked_frames(sk);
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 03/19] Bluetooth: Fix memory leak of S-frames into L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-3-git-send-email-padovan@profusion.mobi>

l2cap_data_channel do not free the S-frame, so we free it here.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index ab3f0c4..a020b9f 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3559,6 +3559,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 		break;
 	}
 
+	kfree_skb(skb);
 	return 0;
 }
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 04/19] Bluetooth: Check the minimum {I,S}-frame size into L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-4-git-send-email-padovan@profusion.mobi>

All packets with size fewer than the minimum specified is dropped.
Note that the size of the l2cap basic header, FCS and SAR fields are
already subtracted of len at the moment of the size check.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   14 +++++++++++---
 1 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index a020b9f..e78fc16 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3619,10 +3619,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (l2cap_check_fcs(pi, skb))
 			goto drop;
 
-		if (__is_iframe(control))
+		if (__is_iframe(control)) {
+			if (len < 4)
+				goto drop;
+
 			l2cap_data_channel_iframe(sk, control, skb);
-		else
+		} else {
+			if (len != 0)
+				goto drop;
+
 			l2cap_data_channel_sframe(sk, control, skb);
+		}
 
 		goto done;
 
@@ -3637,7 +3644,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (pi->fcs == L2CAP_FCS_CRC16)
 			len -= 2;
 
-		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control))
+		if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || len < 4
+				|| __is_sframe(control))
 			goto drop;
 
 		if (l2cap_check_fcs(pi, skb))
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 05/19] Bluetooth: Check if SDU size is greater than MTU on L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-5-git-send-email-padovan@profusion.mobi>

After reassembly the SDU we need to check his size. It can't overflow
the MTU size.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e78fc16..36fac64 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3269,15 +3269,19 @@ static int l2cap_sar_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 co
 		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
 		pi->partial_sdu_len += skb->len;
 
+		if (pi->partial_sdu_len > pi->imtu)
+			goto drop;
+
 		if (pi->partial_sdu_len == pi->sdu_len) {
 			_skb = skb_clone(pi->sdu, GFP_ATOMIC);
 			err = sock_queue_rcv_skb(sk, _skb);
 			if (err < 0)
 				kfree_skb(_skb);
 		}
-		kfree_skb(pi->sdu);
 		err = 0;
 
+drop:
+		kfree_skb(pi->sdu);
 		break;
 	}
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 06/19] Bluetooth: Fix expected_tx_seq calculation on L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-6-git-send-email-padovan@profusion.mobi>

All operation related to the txWindow should be modulo 64.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 36fac64..03caa2c 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3660,7 +3660,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		if (pi->expected_tx_seq == tx_seq)
 			pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
 		else
-			pi->expected_tx_seq = tx_seq + 1;
+			pi->expected_tx_seq = (tx_seq + 1) % 64;
 
 		l2cap_sar_reassembly_sdu(sk, skb, control);
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 07/19] Bluetooth: Implement SendAck() Action on ERTM.
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-7-git-send-email-padovan@profusion.mobi>

Shall be used to ack received frames, It must decide type of
acknowledgment between a RR frame, a RNR frame or transmission of
pending I-frames.
It also modifies l2cap_ertm_send() to report the number of frames sent.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   41 +++++++++++++++++++++++++++++------------
 1 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 03caa2c..6368cb2 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -352,6 +352,11 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
 	count = min_t(unsigned int, conn->mtu, hlen);
 	control |= L2CAP_CTRL_FRAME_TYPE;
 
+	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+		control |= L2CAP_CTRL_FINAL;
+		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+	}
+
 	skb = bt_skb_alloc(count, GFP_ATOMIC);
 	if (!skb)
 		return -ENOMEM;
@@ -1363,7 +1368,7 @@ static int l2cap_ertm_send(struct sock *sk)
 	struct sk_buff *skb, *tx_skb;
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	u16 control, fcs;
-	int err;
+	int err, nsent = 0;
 
 	if (pi->conn_state & L2CAP_CONN_WAIT_F)
 		return 0;
@@ -1413,8 +1418,27 @@ static int l2cap_ertm_send(struct sock *sk)
 			sk->sk_send_head = NULL;
 		else
 			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
+
+		nsent++;
 	}
 
+	return nsent;
+}
+
+static int l2cap_send_ack(struct l2cap_pinfo *pi)
+{
+	struct sock *sk = (struct sock *)pi;
+	u16 control = 0;
+
+	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		control |= L2CAP_SUPER_RCV_NOT_READY;
+		return l2cap_send_sframe(pi, control);
+	} else if (l2cap_ertm_send(sk) == 0) {
+		control |= L2CAP_SUPER_RCV_READY;
+		return l2cap_send_sframe(pi, control);
+	}
 	return 0;
 }
 
@@ -1673,7 +1697,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 		else
 			err = l2cap_ertm_send(sk);
 
-		if (!err)
+		if (err >= 0)
 			err = len;
 		break;
 
@@ -3170,10 +3194,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
 	if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
 			pi->frames_sent == 0) {
 		control |= L2CAP_SUPER_RCV_READY;
-		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
-			control |= L2CAP_CTRL_FINAL;
-			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-		}
 		l2cap_send_sframe(pi, control);
 	}
 }
@@ -3354,7 +3374,6 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	u8 tx_seq = __get_txseq(rx_control);
 	u8 req_seq = __get_reqseq(rx_control);
-	u16 tx_control = 0;
 	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
 	int err = 0;
 
@@ -3441,11 +3460,9 @@ expected:
 		return err;
 
 	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
-	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1) {
-		tx_control |= L2CAP_SUPER_RCV_READY;
-		tx_control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-		l2cap_send_sframe(pi, tx_control);
-	}
+	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
+		l2cap_send_ack(pi);
+
 	return 0;
 }
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 08/19] Bluetooth: Move set of P-bit to l2cap_send_sframe()
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-8-git-send-email-padovan@profusion.mobi>

Abstract the send of of P-bit and avoids code duplication like we
did with the setting of F-bit.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 6368cb2..2e1884b 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -357,6 +357,11 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
 		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
 	}
 
+	if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
+		control |= L2CAP_CTRL_POLL;
+		pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
+	}
+
 	skb = bt_skb_alloc(count, GFP_ATOMIC);
 	if (!skb)
 		return -ENOMEM;
@@ -3356,10 +3361,6 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
 	while (tx_seq != pi->expected_tx_seq) {
 		control = L2CAP_SUPER_SELECT_REJECT;
 		control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-		if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
-			control |= L2CAP_CTRL_POLL;
-			pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
-		}
 		l2cap_send_sframe(pi, control);
 
 		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 09/19] Bluetooth: Add Recv RR (P=0)(F=0) for SREJ_SENT state on ERTM
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-9-git-send-email-padovan@profusion.mobi>

This finishes the implementation of Recv RR (P=0)(F=0) for the Enhanced
Retransmission Mode on L2CAP.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2e1884b..4dd130d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3509,7 +3509,10 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 				__mod_retrans_timer();
 
 			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-			l2cap_ertm_send(sk);
+			if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
+				l2cap_send_ack(pi);
+			else
+				l2cap_ertm_send(sk);
 		}
 		break;
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 10/19] Bluetooth: Use a l2cap_pinfo struct instead l2cap_pi() macro
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-10-git-send-email-padovan@profusion.mobi>

Trivial clean up.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4dd130d..428be03 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1300,7 +1300,7 @@ static int l2cap_streaming_send(struct sock *sk)
 		control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
-		if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) {
+		if (pi->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);
 		}
@@ -1353,7 +1353,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
 				| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
-		if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) {
+		if (pi->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);
 		}
@@ -1401,7 +1401,7 @@ static int l2cap_ertm_send(struct sock *sk)
 		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
 
 
-		if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16) {
+		if (pi->fcs == L2CAP_FCS_CRC16) {
 			fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
 			put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
 		}
@@ -3576,10 +3576,10 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
 		pi->expected_ack_seq = tx_seq;
 		l2cap_drop_acked_frames(sk);
 
-		del_timer(&l2cap_pi(sk)->retrans_timer);
+		del_timer(&pi->retrans_timer);
 		if (rx_control & L2CAP_CTRL_POLL) {
 			u16 control = L2CAP_CTRL_FINAL;
-			l2cap_send_rr_or_rnr(l2cap_pi(sk), control);
+			l2cap_send_rr_or_rnr(pi, control);
 		}
 		break;
 	}
@@ -3688,7 +3688,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 		goto done;
 
 	default:
-		BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode);
+		BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
 		break;
 	}
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 11/19] Bluetooth: Fix ACL MTU issue
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-11-git-send-email-padovan@profusion.mobi>

ERTM and Streaming Modes was having problems when the ACL MTU is lower
than MPS. The 'minus 10' is to take in account the header and fcs
lenghts.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 428be03..12104f4 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2297,6 +2297,8 @@ done:
 		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 > pi->conn->mtu - 10)
+			rfc.max_pdu_size = pi->conn->mtu - 10;
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
@@ -2318,6 +2320,8 @@ done:
 		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 > pi->conn->mtu - 10)
+			rfc.max_pdu_size = pi->conn->mtu - 10;
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
 					sizeof(rfc), (unsigned long) &rfc);
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 12/19] Bluetooth: Split l2cap_data_channel_sframe()
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-12-git-send-email-padovan@profusion.mobi>

Create a function for each type fo S-frame and avoid a lot of nested
code.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |  205 ++++++++++++++++++++++++++++---------------------
 1 files changed, 116 insertions(+), 89 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 12104f4..2f32e91 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3471,120 +3471,147 @@ expected:
 	return 0;
 }
 
-static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	u8 tx_seq = __get_reqseq(rx_control);
 
-	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
-
-	if (L2CAP_CTRL_FINAL & rx_control) {
-		del_timer(&pi->monitor_timer);
-		if (pi->unacked_frames > 0)
-			__mod_retrans_timer();
-		pi->conn_state &= ~L2CAP_CONN_WAIT_F;
-	}
+	if (rx_control & L2CAP_CTRL_POLL) {
+		l2cap_send_i_or_rr_or_rnr(sk);
+		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
-	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
-	case L2CAP_SUPER_RCV_READY:
-		if (rx_control & L2CAP_CTRL_POLL) {
-			l2cap_send_i_or_rr_or_rnr(sk);
-			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
-		} else if (rx_control & L2CAP_CTRL_FINAL) {
-			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-			pi->expected_ack_seq = tx_seq;
-			l2cap_drop_acked_frames(sk);
-
-			if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-				pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
-			else {
-				sk->sk_send_head = TX_QUEUE(sk)->next;
-				pi->next_tx_seq = pi->expected_ack_seq;
-				l2cap_ertm_send(sk);
-			}
+	} else if (rx_control & L2CAP_CTRL_FINAL) {
+		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		pi->expected_ack_seq = tx_seq;
+		l2cap_drop_acked_frames(sk);
 
-		} else {
-			pi->expected_ack_seq = tx_seq;
-			l2cap_drop_acked_frames(sk);
+		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
+			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+		else {
+			sk->sk_send_head = TX_QUEUE(sk)->next;
+			pi->next_tx_seq = pi->expected_ack_seq;
+			l2cap_ertm_send(sk);
+		}
 
-			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-			    (pi->unacked_frames > 0))
-				__mod_retrans_timer();
+	} else {
+		pi->expected_ack_seq = tx_seq;
+		l2cap_drop_acked_frames(sk);
 
-			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-			if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
-				l2cap_send_ack(pi);
-			else
-				l2cap_ertm_send(sk);
-		}
-		break;
+		if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+				(pi->unacked_frames > 0))
+			__mod_retrans_timer();
 
-	case L2CAP_SUPER_REJECT:
 		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
+			l2cap_send_ack(pi);
+		else
+			l2cap_ertm_send(sk);
+	}
+}
 
-		pi->expected_ack_seq = __get_reqseq(rx_control);
-		l2cap_drop_acked_frames(sk);
+static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
 
-		if (rx_control & L2CAP_CTRL_FINAL) {
-			if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-				pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
-			else {
-				sk->sk_send_head = TX_QUEUE(sk)->next;
-				pi->next_tx_seq = pi->expected_ack_seq;
-				l2cap_ertm_send(sk);
-			}
-		} else {
+	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+
+	pi->expected_ack_seq = __get_reqseq(rx_control);
+	l2cap_drop_acked_frames(sk);
+
+	if (rx_control & L2CAP_CTRL_FINAL) {
+		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
+			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+		else {
 			sk->sk_send_head = TX_QUEUE(sk)->next;
 			pi->next_tx_seq = pi->expected_ack_seq;
 			l2cap_ertm_send(sk);
-
-			if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-				pi->srej_save_reqseq = tx_seq;
-				pi->conn_state |= L2CAP_CONN_REJ_ACT;
-			}
 		}
+	} else {
+		sk->sk_send_head = TX_QUEUE(sk)->next;
+		pi->next_tx_seq = pi->expected_ack_seq;
+		l2cap_ertm_send(sk);
 
-		break;
+		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
+			pi->srej_save_reqseq = tx_seq;
+			pi->conn_state |= L2CAP_CONN_REJ_ACT;
+		}
+	}
+}
+static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
 
-	case L2CAP_SUPER_SELECT_REJECT:
-		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
-		if (rx_control & L2CAP_CTRL_POLL) {
-			pi->expected_ack_seq = tx_seq;
-			l2cap_drop_acked_frames(sk);
-			l2cap_retransmit_frame(sk, tx_seq);
-			l2cap_ertm_send(sk);
-			if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-				pi->srej_save_reqseq = tx_seq;
-				pi->conn_state |= L2CAP_CONN_SREJ_ACT;
-			}
-		} else if (rx_control & L2CAP_CTRL_FINAL) {
-			if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
-					pi->srej_save_reqseq == tx_seq)
-				pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
-			else
-				l2cap_retransmit_frame(sk, tx_seq);
+	if (rx_control & L2CAP_CTRL_POLL) {
+		pi->expected_ack_seq = tx_seq;
+		l2cap_drop_acked_frames(sk);
+		l2cap_retransmit_frame(sk, tx_seq);
+		l2cap_ertm_send(sk);
+		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
+			pi->srej_save_reqseq = tx_seq;
+			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
 		}
-		else {
+	} else if (rx_control & L2CAP_CTRL_FINAL) {
+		if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
+				pi->srej_save_reqseq == tx_seq)
+			pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+		else
 			l2cap_retransmit_frame(sk, tx_seq);
-			if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-				pi->srej_save_reqseq = tx_seq;
-				pi->conn_state |= L2CAP_CONN_SREJ_ACT;
-			}
+	}
+	else {
+		l2cap_retransmit_frame(sk, tx_seq);
+		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
+			pi->srej_save_reqseq = tx_seq;
+			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
 		}
+	}
+}
+
+static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
+
+	pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+	pi->expected_ack_seq = tx_seq;
+	l2cap_drop_acked_frames(sk);
+
+	del_timer(&pi->retrans_timer);
+	if (rx_control & L2CAP_CTRL_POLL) {
+		u16 control = L2CAP_CTRL_FINAL;
+		l2cap_send_rr_or_rnr(pi, control);
+	}
+}
+
+static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+{
+	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+
+	if (L2CAP_CTRL_FINAL & rx_control) {
+		del_timer(&l2cap_pi(sk)->monitor_timer);
+		if (l2cap_pi(sk)->unacked_frames > 0)
+			__mod_retrans_timer();
+		l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
+	}
+
+	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
+	case L2CAP_SUPER_RCV_READY:
+		l2cap_data_channel_rrframe(sk, rx_control);
 		break;
 
-	case L2CAP_SUPER_RCV_NOT_READY:
-		pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
-		pi->expected_ack_seq = tx_seq;
-		l2cap_drop_acked_frames(sk);
+	case L2CAP_SUPER_REJECT:
+		l2cap_data_channel_rejframe(sk, rx_control);
+		break;
 
-		del_timer(&pi->retrans_timer);
-		if (rx_control & L2CAP_CTRL_POLL) {
-			u16 control = L2CAP_CTRL_FINAL;
-			l2cap_send_rr_or_rnr(pi, control);
-		}
+	case L2CAP_SUPER_SELECT_REJECT:
+		l2cap_data_channel_srejframe(sk, rx_control);
+		break;
+
+	case L2CAP_SUPER_RCV_NOT_READY:
+		l2cap_data_channel_rnrframe(sk, rx_control);
 		break;
 	}
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 13/19] Bluetooth: Handle all cases of receipt of RNR-frames into L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-13-git-send-email-padovan@profusion.mobi>

We weren't handling the receipt under SREJ_SENT state table.
It also introduce l2cap_send_srejtail(). It will be used in the nexts
commits too.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 2f32e91..f966ed3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1447,6 +1447,22 @@ static int l2cap_send_ack(struct l2cap_pinfo *pi)
 	return 0;
 }
 
+static int l2cap_send_srejtail(struct sock *sk)
+{
+	struct srej_list *tail;
+	u16 control;
+
+	control = L2CAP_SUPER_SELECT_REJECT;
+	control |= L2CAP_CTRL_FINAL;
+
+	tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
+	control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	l2cap_send_sframe(l2cap_pi(sk), control);
+
+	return 0;
+}
+
 static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
 {
 	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -3579,11 +3595,19 @@ static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
 	pi->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(sk);
 
-	del_timer(&pi->retrans_timer);
-	if (rx_control & L2CAP_CTRL_POLL) {
-		u16 control = L2CAP_CTRL_FINAL;
-		l2cap_send_rr_or_rnr(pi, control);
+	if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
+		del_timer(&pi->retrans_timer);
+		if (rx_control & L2CAP_CTRL_POLL) {
+			u16 control = L2CAP_CTRL_FINAL;
+			l2cap_send_rr_or_rnr(pi, control);
+		}
+		return;
 	}
+
+	if (rx_control & L2CAP_CTRL_POLL)
+		l2cap_send_srejtail(sk);
+	else
+		l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
 }
 
 static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 14/19] Bluetooth: Group the ack of I-frames into l2cap_data_channel_rrframe()
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-14-git-send-email-padovan@profusion.mobi>

It also fix a bug: we weren't acknowledging I-frames when P=1.
Note that when F=1 we are acknowledging packets before setting
RemoteBusy to False. The spec says we should do that in the opposite
order, but acknowledment of packets doesn't care about RemoteBusy flag
so we can do that in the order we want.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index f966ed3..d6667fa 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3490,7 +3490,9 @@ expected:
 static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 tx_seq = __get_reqseq(rx_control);
+
+	pi->expected_ack_seq = __get_reqseq(rx_control);
+	l2cap_drop_acked_frames(sk);
 
 	if (rx_control & L2CAP_CTRL_POLL) {
 		l2cap_send_i_or_rr_or_rnr(sk);
@@ -3498,8 +3500,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
 
 	} else if (rx_control & L2CAP_CTRL_FINAL) {
 		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-		pi->expected_ack_seq = tx_seq;
-		l2cap_drop_acked_frames(sk);
 
 		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
 			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
@@ -3510,9 +3510,6 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
 		}
 
 	} else {
-		pi->expected_ack_seq = tx_seq;
-		l2cap_drop_acked_frames(sk);
-
 		if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
 				(pi->unacked_frames > 0))
 			__mod_retrans_timer();
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 15/19] Bluetooth: Remove duplicate use of __get_reqseq() macro on L2CAP
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-15-git-send-email-padovan@profusion.mobi>

tx_seq var already has the value of __get_reqseq().

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index d6667fa..9546f59 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3529,7 +3529,7 @@ static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
 
 	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
 
-	pi->expected_ack_seq = __get_reqseq(rx_control);
+	pi->expected_ack_seq = tx_seq;
 	l2cap_drop_acked_frames(sk);
 
 	if (rx_control & L2CAP_CTRL_FINAL) {
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 16/19] Bluetooth: Finish implementation for Rec RR (P=1) on ERTM
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-16-git-send-email-padovan@profusion.mobi>

Now the code handles the case under SREJ_SENT state.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 9546f59..85f97b9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3495,8 +3495,17 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
 	l2cap_drop_acked_frames(sk);
 
 	if (rx_control & L2CAP_CTRL_POLL) {
-		l2cap_send_i_or_rr_or_rnr(sk);
-		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+					(pi->unacked_frames > 0))
+				__mod_retrans_timer();
+
+			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+			l2cap_send_srejtail(sk);
+		} else {
+			l2cap_send_i_or_rr_or_rnr(sk);
+			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		}
 
 	} else if (rx_control & L2CAP_CTRL_FINAL) {
 		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 17/19] Bluetooth: Ignore I-frames with a duplicated txSeq
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-17-git-send-email-padovan@profusion.mobi>

L2CAP Enhanced Retransmission Mode shall ignore all I-frames with a
duplicated txSeq.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 85f97b9..b431dc5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3413,6 +3413,13 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
 	if (tx_seq == pi->expected_tx_seq)
 		goto expected;
 
+	/* Check for duplicated tx_seq. This actually
+	 * subtracts 1 from expected_tx_seq */
+	if (tx_seq == (pi->expected_tx_seq + 63) % 64) {
+		kfree_skb(skb);
+		return 0;
+	}
+
 	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
 		struct srej_list *first;
 
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 18/19] Bluetooth: Add timer to Acknowledge I-frames
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-18-git-send-email-padovan@profusion.mobi>

We ack I-frames on each txWindow/5 I-frames received, but if the sender
stop to send I-frames and it's not a txWindow multiple we can leave some
frames unacked.
So I added a timer to ack I-frames on this case. The timer expires in
200ms.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    4 ++++
 net/bluetooth/l2cap.c         |   15 +++++++++++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d9c20c3..48f10f4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -35,6 +35,7 @@
 #define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
 #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
 #define L2CAP_DEFAULT_MAX_PDU_SIZE	672
+#define L2CAP_DEFAULT_ACK_TO		200
 
 #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
 #define L2CAP_INFO_TIMEOUT	(4000)  /*  4 seconds */
@@ -348,6 +349,7 @@ struct l2cap_pinfo {
 
 	struct timer_list	retrans_timer;
 	struct timer_list	monitor_timer;
+	struct timer_list	ack_timer;
 	struct sk_buff_head	tx_queue;
 	struct sk_buff_head	srej_queue;
 	struct srej_list	srej_l;
@@ -382,6 +384,8 @@ struct l2cap_pinfo {
 		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
 #define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \
 		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
+#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \
+		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
 
 static inline int l2cap_tx_window_full(struct sock *sk)
 {
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index b431dc5..0dc7b95 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -2230,6 +2230,15 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 	*ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
+static void l2cap_ack_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+
+	bh_lock_sock(sk);
+	l2cap_send_ack(l2cap_pi(sk));
+	bh_unlock_sock(sk);
+}
+
 static inline void l2cap_ertm_init(struct sock *sk)
 {
 	l2cap_pi(sk)->expected_ack_seq = 0;
@@ -2242,6 +2251,8 @@ static inline void l2cap_ertm_init(struct sock *sk)
 			l2cap_retrans_timeout, (unsigned long) sk);
 	setup_timer(&l2cap_pi(sk)->monitor_timer,
 			l2cap_monitor_timeout, (unsigned long) sk);
+	setup_timer(&l2cap_pi(sk)->ack_timer,
+			l2cap_ack_timeout, (unsigned long) sk);
 
 	__skb_queue_head_init(SREJ_QUEUE(sk));
 }
@@ -2970,6 +2981,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 		skb_queue_purge(SREJ_QUEUE(sk));
 		del_timer(&l2cap_pi(sk)->retrans_timer);
 		del_timer(&l2cap_pi(sk)->monitor_timer);
+		del_timer(&l2cap_pi(sk)->ack_timer);
 	}
 
 	l2cap_chan_del(sk, ECONNRESET);
@@ -3000,6 +3012,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 		skb_queue_purge(SREJ_QUEUE(sk));
 		del_timer(&l2cap_pi(sk)->retrans_timer);
 		del_timer(&l2cap_pi(sk)->monitor_timer);
+		del_timer(&l2cap_pi(sk)->ack_timer);
 	}
 
 	l2cap_chan_del(sk, 0);
@@ -3487,6 +3500,8 @@ expected:
 	if (err < 0)
 		return err;
 
+	__mod_ack_timer();
+
 	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
 	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
 		l2cap_send_ack(pi);
-- 
1.6.4.4

^ permalink raw reply related

* [PATCH 19/19] Bluetooth: Move specific Basic Mode code to the right place
From: Gustavo F. Padovan @ 2010-03-23 19:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, gustavo, jprvita, ulisses
In-Reply-To: <1269373726-13209-19-git-send-email-padovan@profusion.mobi>

Inside "case L2CAP_MODE_BASIC:" we don't need to check for sk_type and
L2CAP mode. So only the length check is fine.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
---
 net/bluetooth/l2cap.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 0dc7b95..8c8b5d9 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1660,11 +1660,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 	if (msg->msg_flags & MSG_OOB)
 		return -EOPNOTSUPP;
 
-	/* Check outgoing MTU */
-	if (sk->sk_type == SOCK_SEQPACKET && pi->mode == L2CAP_MODE_BASIC &&
-	    len > pi->omtu)
-		return -EINVAL;
-
 	lock_sock(sk);
 
 	if (sk->sk_state != BT_CONNECTED) {
@@ -1681,6 +1676,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 
 	switch (pi->mode) {
 	case L2CAP_MODE_BASIC:
+		/* Check outgoing MTU */
+		if (len > pi->omtu) {
+			err = -EINVAL;
+			goto done;
+		}
+
 		/* Create a basic PDU */
 		skb = l2cap_create_basic_pdu(sk, msg, len);
 		if (IS_ERR(skb)) {
-- 
1.6.4.4

^ permalink raw reply related

* [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP
From: Gustavo F. Padovan @ 2010-03-23 20:39 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel

Hi People,

I was thinking about a release plan for Enhanced Retransmission Mode,
Streaming Mode, Frame Check Sequence(FCS) and Segmentation and
Reassembly(SAR).

2.6.35: Upstream Streaming Mode, FCS, SAR and add a sub-menu option
to L2CAP at Kconfig for ERTM with an EXPERIMENTAL flag. So we will have
a chance to test ERTM more intensively.

2.6.36: Upstream ERTM. After that ERTM will be the default mode with
SOCK_STREAM and also enabled by default under L2CAP. If you think it's
not worth release Streaming Mode, FCS and SAR without ERTM we can
upstream them together on 2.6.36.

Comments, ideas?

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* RE: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow
From: Mike Tsai @ 2010-03-23 22:10 UTC (permalink / raw)
  To: Gustavo F. Padovan
  Cc: linux-bluetooth@vger.kernel.org, marcel@holtmann.org,
	mathewm@codeaurora.org
In-Reply-To: <20100322033342.GA11242@vigoh>

Hi Gustavo,

	Thanks for your reply. It seems to be a reasonable approach. 

	There are no BT 3.0 products on the market that support extended window size yet (up to 16000+ TxWin?), and I don't think it will be supported in the near future either,

Best Regards,

Mike


-----Original Message-----
From: Gustavo F. Padovan [mailto:gfpadovan@gmail.com] On Behalf Of Gustavo F. Padovan
Sent: Sunday, March 21, 2010 8:34 PM
To: Mike Tsai
Cc: linux-bluetooth@vger.kernel.org; marcel@holtmann.org; mathewm@codeaurora.org
Subject: Re: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow

Hi Mike,

* Mike Tsai <Mike.Tsai@Atheros.com> [2010-03-17 14:47:49 -0700]:

> Just out of curiosity, where does this (pi->txWindow/6 + 1) come from?

L2CAP spec says that we don't need to ack every packet received, so I
have choose this number for optimization to not send an ack for each
packet received.
We can do a study and choose the better value for this, but it's better
to have the Extended Tx Window Implemented.

> 
> Thanks,
> 
> Mike
> 
> 
> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
> Sent: Wednesday, March 17, 2010 11:54 AM
> To: linux-bluetooth@vger.kernel.org
> Cc: marcel@holtmann.org; gustavo@padovan.org; mathewm@codeaurora.org
> Subject: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow
> 
> Now that we can set the txWindow we need to change the acknowledgement
> procedure to ack after each (pi->txWindow/6 + 1). The plus 1 is to avoid
> the zero value.
> It also renames pi->num_to_ack to a better name: pi->num_acked.
> 
> Signed-off-by: Gustavo F. Padovan <gustavo@padovan.org>
> ---
>  include/net/bluetooth/l2cap.h |    3 +--
>  net/bluetooth/l2cap.c         |    9 +++++----
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index c7bf676..9358b9e 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -30,7 +30,6 @@
>  #define L2CAP_DEFAULT_MIN_MTU		48
>  #define L2CAP_DEFAULT_FLUSH_TO		0xffff
>  #define L2CAP_DEFAULT_TX_WINDOW		63
> -#define L2CAP_DEFAULT_NUM_TO_ACK        (L2CAP_DEFAULT_TX_WINDOW/5)
>  #define L2CAP_DEFAULT_MAX_TX		3
>  #define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
>  #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
> @@ -333,7 +332,7 @@ struct l2cap_pinfo {
>  	__u8		frames_sent;
>  	__u8		unacked_frames;
>  	__u8		retry_count;
> -	__u8		num_to_ack;
> +	__u8		num_acked;
>  	__u16		sdu_len;
>  	__u16		partial_sdu_len;
>  	struct sk_buff	*sdu;
> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> index 6679418..959be0f 100644
> --- a/net/bluetooth/l2cap.c
> +++ b/net/bluetooth/l2cap.c
> @@ -2248,7 +2248,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
>  	l2cap_pi(sk)->expected_ack_seq = 0;
>  	l2cap_pi(sk)->unacked_frames = 0;
>  	l2cap_pi(sk)->buffer_seq = 0;
> -	l2cap_pi(sk)->num_to_ack = 0;
> +	l2cap_pi(sk)->num_acked = 0;
>  	l2cap_pi(sk)->frames_sent = 0;
>  
>  	setup_timer(&l2cap_pi(sk)->retrans_timer,
> @@ -2571,7 +2571,7 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
>  	if (*result == L2CAP_CONF_SUCCESS) {
>  		switch (rfc.mode) {
>  		case L2CAP_MODE_ERTM:
> -			pi->remote_tx_win   = rfc.txwin_size;
> +			pi->tx_win   = rfc.txwin_size;
>  			pi->retrans_timeout = rfc.retrans_timeout;
>  			pi->monitor_timeout = rfc.monitor_timeout;
>  			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
> @@ -3408,6 +3408,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
>  	u8 tx_seq = __get_txseq(rx_control);
>  	u8 req_seq = __get_reqseq(rx_control);
>  	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
> +	int num_to_ack = (pi->tx_win/6) + 1;
>  	int err = 0;
>  
>  	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
> @@ -3501,8 +3502,8 @@ expected:
>  
>  	__mod_ack_timer();
>  
> -	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
> -	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
> +	pi->num_acked = (pi->num_acked + 1) % num_to_ack;
> +	if (pi->num_acked == num_to_ack - 1)
>  		l2cap_send_ack(pi);
>  
>  	return 0;
> -- 
> 1.6.4.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow
From: Gustavo F. Padovan @ 2010-03-23 22:35 UTC (permalink / raw)
  To: Mike Tsai; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <35B17FE5076C7040809188FBE7913F983A1DDCF356@SC1EXMB-MBCL.global.atheros.com>


Hi Mike,

Please do not top post on this mailing list.


* Mike Tsai <Mike.Tsai@Atheros.com> [2010-03-23 15:10:29 -0700]:

> Hi Gustavo,
> 
> 	Thanks for your reply. It seems to be a reasonable approach. 
> 
> 	There are no BT 3.0 products on the market that support extended window size yet (up to 16000+ TxWin?), and I don't think it will be supported in the near future either,

AFAIK we don't need a 3.0 hardware to have Extended TxWindow working.
It is an L2CAP protocol feature. The hardware lower layers has no idea
about the L2CAP txWin size.

> 
> Best Regards,
> 
> Mike
> 
> 
> -----Original Message-----
> From: Gustavo F. Padovan [mailto:gfpadovan@gmail.com] On Behalf Of Gustavo F. Padovan
> Sent: Sunday, March 21, 2010 8:34 PM
> To: Mike Tsai
> Cc: linux-bluetooth@vger.kernel.org; marcel@holtmann.org; mathewm@codeaurora.org
> Subject: Re: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow
> 
> Hi Mike,
> 
> * Mike Tsai <Mike.Tsai@Atheros.com> [2010-03-17 14:47:49 -0700]:
> 
> > Just out of curiosity, where does this (pi->txWindow/6 + 1) come from?
> 
> L2CAP spec says that we don't need to ack every packet received, so I
> have choose this number for optimization to not send an ack for each
> packet received.
> We can do a study and choose the better value for this, but it's better
> to have the Extended Tx Window Implemented.
> 
> > 
> > Thanks,
> > 
> > Mike
> > 
> > 
> > -----Original Message-----
> > From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
> > Sent: Wednesday, March 17, 2010 11:54 AM
> > To: linux-bluetooth@vger.kernel.org
> > Cc: marcel@holtmann.org; gustavo@padovan.org; mathewm@codeaurora.org
> > Subject: [PATCH 2/4] Bluetooth: Change acknowledgement to use the value of txWindow
> > 
> > Now that we can set the txWindow we need to change the acknowledgement
> > procedure to ack after each (pi->txWindow/6 + 1). The plus 1 is to avoid
> > the zero value.
> > It also renames pi->num_to_ack to a better name: pi->num_acked.
> > 
> > Signed-off-by: Gustavo F. Padovan <gustavo@padovan.org>
> > ---
> >  include/net/bluetooth/l2cap.h |    3 +--
> >  net/bluetooth/l2cap.c         |    9 +++++----
> >  2 files changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> > index c7bf676..9358b9e 100644
> > --- a/include/net/bluetooth/l2cap.h
> > +++ b/include/net/bluetooth/l2cap.h
> > @@ -30,7 +30,6 @@
> >  #define L2CAP_DEFAULT_MIN_MTU		48
> >  #define L2CAP_DEFAULT_FLUSH_TO		0xffff
> >  #define L2CAP_DEFAULT_TX_WINDOW		63
> > -#define L2CAP_DEFAULT_NUM_TO_ACK        (L2CAP_DEFAULT_TX_WINDOW/5)
> >  #define L2CAP_DEFAULT_MAX_TX		3
> >  #define L2CAP_DEFAULT_RETRANS_TO	1000    /* 1 second */
> >  #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
> > @@ -333,7 +332,7 @@ struct l2cap_pinfo {
> >  	__u8		frames_sent;
> >  	__u8		unacked_frames;
> >  	__u8		retry_count;
> > -	__u8		num_to_ack;
> > +	__u8		num_acked;
> >  	__u16		sdu_len;
> >  	__u16		partial_sdu_len;
> >  	struct sk_buff	*sdu;
> > diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> > index 6679418..959be0f 100644
> > --- a/net/bluetooth/l2cap.c
> > +++ b/net/bluetooth/l2cap.c
> > @@ -2248,7 +2248,7 @@ static inline void l2cap_ertm_init(struct sock *sk)
> >  	l2cap_pi(sk)->expected_ack_seq = 0;
> >  	l2cap_pi(sk)->unacked_frames = 0;
> >  	l2cap_pi(sk)->buffer_seq = 0;
> > -	l2cap_pi(sk)->num_to_ack = 0;
> > +	l2cap_pi(sk)->num_acked = 0;
> >  	l2cap_pi(sk)->frames_sent = 0;
> >  
> >  	setup_timer(&l2cap_pi(sk)->retrans_timer,
> > @@ -2571,7 +2571,7 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
> >  	if (*result == L2CAP_CONF_SUCCESS) {
> >  		switch (rfc.mode) {
> >  		case L2CAP_MODE_ERTM:
> > -			pi->remote_tx_win   = rfc.txwin_size;
> > +			pi->tx_win   = rfc.txwin_size;
> >  			pi->retrans_timeout = rfc.retrans_timeout;
> >  			pi->monitor_timeout = rfc.monitor_timeout;
> >  			pi->max_pdu_size    = le16_to_cpu(rfc.max_pdu_size);
> > @@ -3408,6 +3408,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
> >  	u8 tx_seq = __get_txseq(rx_control);
> >  	u8 req_seq = __get_reqseq(rx_control);
> >  	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
> > +	int num_to_ack = (pi->tx_win/6) + 1;
> >  	int err = 0;
> >  
> >  	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
> > @@ -3501,8 +3502,8 @@ expected:
> >  
> >  	__mod_ack_timer();
> >  
> > -	pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
> > -	if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
> > +	pi->num_acked = (pi->num_acked + 1) % num_to_ack;
> > +	if (pi->num_acked == num_to_ack - 1)
> >  		l2cap_send_ack(pi);
> >  
> >  	return 0;
> > -- 
> > 1.6.4.4
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> -- 
> Gustavo F. Padovan
> http://padovan.org
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* RE: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP
From: Mike Tsai @ 2010-03-23 23:36 UTC (permalink / raw)
  To: Gustavo F. Padovan, linux-bluetooth@vger.kernel.org; +Cc: marcel@holtmann.org
In-Reply-To: <20100323203903.GA13897@vigoh>

Hi Gus,

	My comments will be that it is probably better to implement eRTM mode first because many existing implementations do not support stream mode but definitely support eRTM mode. 

	You shall be able to verify the testing with Bluetooth SIG PTS,

Thanks,

Mike

-----Original Message-----
From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Gustavo F. Padovan
Sent: Tuesday, March 23, 2010 1:39 PM
To: linux-bluetooth@vger.kernel.org
Cc: marcel@holtmann.org
Subject: [RFC] Release Plan for ERTM, Streaming Mode, FCS and SAR on L2CAP

Hi People,

I was thinking about a release plan for Enhanced Retransmission Mode,
Streaming Mode, Frame Check Sequence(FCS) and Segmentation and
Reassembly(SAR).

2.6.35: Upstream Streaming Mode, FCS, SAR and add a sub-menu option
to L2CAP at Kconfig for ERTM with an EXPERIMENTAL flag. So we will have
a chance to test ERTM more intensively.

2.6.36: Upstream ERTM. After that ERTM will be the default mode with
SOCK_STREAM and also enabled by default under L2CAP. If you think it's
not worth release Streaming Mode, FCS and SAR without ERTM we can
upstream them together on 2.6.36.

Comments, ideas?

-- 
Gustavo F. Padovan
http://padovan.org
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox