aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <gustavo@las.ic.unicamp.br>2009-10-03 01:34:39 -0400
committerMarcel Holtmann <marcel@holtmann.org>2009-12-03 13:34:24 -0500
commit4ec10d9720ef78cd81d8bcc30a3238665744569f (patch)
treea4be8b2201f9e7acac689443d10cb30a3287972f
parent9f121a5a80b4417c6db5a35e26d2e79c29c3fc0d (diff)
Bluetooth: Implement RejActioned flag
RejActioned is used to prevent retransmission when a entity is on the WAIT_F state, i.e., waiting for a frame with F-bit set due local busy condition or a expired retransmission timer. (When these two events raise they send a frame with the Poll bit set and enters in the WAIT_F state to wait for a frame with the Final bit set.) The local entity doesn't send I-frames(the data frames) until the receipt of a frame with F-bit set. When that happens it also set RejActioned to false. RejActioned is a mandatory feature of ERTM spec. Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--net/bluetooth/l2cap.c38
2 files changed, 36 insertions, 3 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 327eb57dab51..17a689f27a6a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -374,6 +374,7 @@ struct l2cap_pinfo {
374#define L2CAP_CONN_SEND_PBIT 0x10 374#define L2CAP_CONN_SEND_PBIT 0x10
375#define L2CAP_CONN_REMOTE_BUSY 0x20 375#define L2CAP_CONN_REMOTE_BUSY 0x20
376#define L2CAP_CONN_LOCAL_BUSY 0x40 376#define L2CAP_CONN_LOCAL_BUSY 0x40
377#define L2CAP_CONN_REJ_ACT 0x80
377 378
378#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ 379#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \
379 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); 380 jiffies + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 78ab8811e5ef..73bda0ae41d6 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3362,6 +3362,16 @@ expected:
3362 return 0; 3362 return 0;
3363 } 3363 }
3364 3364
3365 if (rx_control & L2CAP_CTRL_FINAL) {
3366 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3367 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3368 else {
3369 sk->sk_send_head = TX_QUEUE(sk)->next;
3370 pi->next_tx_seq = pi->expected_ack_seq;
3371 l2cap_ertm_send(sk);
3372 }
3373 }
3374
3365 pi->buffer_seq = (pi->buffer_seq + 1) % 64; 3375 pi->buffer_seq = (pi->buffer_seq + 1) % 64;
3366 3376
3367 err = l2cap_sar_reassembly_sdu(sk, skb, rx_control); 3377 err = l2cap_sar_reassembly_sdu(sk, skb, rx_control);
@@ -3398,6 +3408,14 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3398 pi->expected_ack_seq = tx_seq; 3408 pi->expected_ack_seq = tx_seq;
3399 l2cap_drop_acked_frames(sk); 3409 l2cap_drop_acked_frames(sk);
3400 3410
3411 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3412 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3413 else {
3414 sk->sk_send_head = TX_QUEUE(sk)->next;
3415 pi->next_tx_seq = pi->expected_ack_seq;
3416 l2cap_ertm_send(sk);
3417 }
3418
3401 if (!(pi->conn_state & L2CAP_CONN_WAIT_F)) 3419 if (!(pi->conn_state & L2CAP_CONN_WAIT_F))
3402 break; 3420 break;
3403 3421
@@ -3425,10 +3443,24 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str
3425 pi->expected_ack_seq = __get_reqseq(rx_control); 3443 pi->expected_ack_seq = __get_reqseq(rx_control);
3426 l2cap_drop_acked_frames(sk); 3444 l2cap_drop_acked_frames(sk);
3427 3445
3428 sk->sk_send_head = TX_QUEUE(sk)->next; 3446 if (rx_control & L2CAP_CTRL_FINAL) {
3429 pi->next_tx_seq = pi->expected_ack_seq; 3447 if (pi->conn_state & L2CAP_CONN_REJ_ACT)
3448 pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
3449 else {
3450 sk->sk_send_head = TX_QUEUE(sk)->next;
3451 pi->next_tx_seq = pi->expected_ack_seq;
3452 l2cap_ertm_send(sk);
3453 }
3454 } else {
3455 sk->sk_send_head = TX_QUEUE(sk)->next;
3456 pi->next_tx_seq = pi->expected_ack_seq;
3457 l2cap_ertm_send(sk);
3430 3458
3431 l2cap_ertm_send(sk); 3459 if (pi->conn_state & L2CAP_CONN_WAIT_F) {
3460 pi->srej_save_reqseq = tx_seq;
3461 pi->conn_state |= L2CAP_CONN_REJ_ACT;
3462 }
3463 }
3432 3464
3433 break; 3465 break;
3434 3466