diff options
author | Gustavo F. Padovan <gustavo@las.ic.unicamp.br> | 2009-10-03 01:34:39 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-12-03 13:34:24 -0500 |
commit | 4ec10d9720ef78cd81d8bcc30a3238665744569f (patch) | |
tree | a4be8b2201f9e7acac689443d10cb30a3287972f | |
parent | 9f121a5a80b4417c6db5a35e26d2e79c29c3fc0d (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.h | 1 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 38 |
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 | ||