diff options
-rw-r--r-- | net/bluetooth/l2cap_core.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index fd324d4cb217..36842a29bb47 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1836,6 +1836,15 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) | |||
1836 | } | 1836 | } |
1837 | } | 1837 | } |
1838 | 1838 | ||
1839 | static void l2cap_retransmit(struct l2cap_chan *chan, | ||
1840 | struct l2cap_ctrl *control) | ||
1841 | { | ||
1842 | BT_DBG("chan %p, control %p", chan, control); | ||
1843 | |||
1844 | l2cap_seq_list_append(&chan->retrans_list, control->reqseq); | ||
1845 | l2cap_ertm_resend(chan); | ||
1846 | } | ||
1847 | |||
1839 | static void l2cap_retransmit_all(struct l2cap_chan *chan, | 1848 | static void l2cap_retransmit_all(struct l2cap_chan *chan, |
1840 | struct l2cap_ctrl *control) | 1849 | struct l2cap_ctrl *control) |
1841 | { | 1850 | { |
@@ -2532,6 +2541,13 @@ static void l2cap_pass_to_tx(struct l2cap_chan *chan, | |||
2532 | l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); | 2541 | l2cap_tx(chan, control, 0, L2CAP_EV_RECV_REQSEQ_AND_FBIT); |
2533 | } | 2542 | } |
2534 | 2543 | ||
2544 | static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, | ||
2545 | struct l2cap_ctrl *control) | ||
2546 | { | ||
2547 | BT_DBG("chan %p, control %p", chan, control); | ||
2548 | l2cap_tx(chan, control, 0, L2CAP_EV_RECV_FBIT); | ||
2549 | } | ||
2550 | |||
2535 | /* Copy frame to all raw sockets on that connection */ | 2551 | /* Copy frame to all raw sockets on that connection */ |
2536 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | 2552 | static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) |
2537 | { | 2553 | { |
@@ -4539,7 +4555,59 @@ static int l2cap_rx_queued_iframes(struct l2cap_chan *chan) | |||
4539 | static void l2cap_handle_srej(struct l2cap_chan *chan, | 4555 | static void l2cap_handle_srej(struct l2cap_chan *chan, |
4540 | struct l2cap_ctrl *control) | 4556 | struct l2cap_ctrl *control) |
4541 | { | 4557 | { |
4542 | /* Placeholder */ | 4558 | struct sk_buff *skb; |
4559 | |||
4560 | BT_DBG("chan %p, control %p", chan, control); | ||
4561 | |||
4562 | if (control->reqseq == chan->next_tx_seq) { | ||
4563 | BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq); | ||
4564 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4565 | return; | ||
4566 | } | ||
4567 | |||
4568 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, control->reqseq); | ||
4569 | |||
4570 | if (skb == NULL) { | ||
4571 | BT_DBG("Seq %d not available for retransmission", | ||
4572 | control->reqseq); | ||
4573 | return; | ||
4574 | } | ||
4575 | |||
4576 | if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) { | ||
4577 | BT_DBG("Retry limit exceeded (%d)", chan->max_tx); | ||
4578 | l2cap_send_disconn_req(chan->conn, chan, ECONNRESET); | ||
4579 | return; | ||
4580 | } | ||
4581 | |||
4582 | clear_bit(CONN_REMOTE_BUSY, &chan->conn_state); | ||
4583 | |||
4584 | if (control->poll) { | ||
4585 | l2cap_pass_to_tx(chan, control); | ||
4586 | |||
4587 | set_bit(CONN_SEND_FBIT, &chan->conn_state); | ||
4588 | l2cap_retransmit(chan, control); | ||
4589 | l2cap_ertm_send(chan); | ||
4590 | |||
4591 | if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { | ||
4592 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
4593 | chan->srej_save_reqseq = control->reqseq; | ||
4594 | } | ||
4595 | } else { | ||
4596 | l2cap_pass_to_tx_fbit(chan, control); | ||
4597 | |||
4598 | if (control->final) { | ||
4599 | if (chan->srej_save_reqseq != control->reqseq || | ||
4600 | !test_and_clear_bit(CONN_SREJ_ACT, | ||
4601 | &chan->conn_state)) | ||
4602 | l2cap_retransmit(chan, control); | ||
4603 | } else { | ||
4604 | l2cap_retransmit(chan, control); | ||
4605 | if (chan->tx_state == L2CAP_TX_STATE_WAIT_F) { | ||
4606 | set_bit(CONN_SREJ_ACT, &chan->conn_state); | ||
4607 | chan->srej_save_reqseq = control->reqseq; | ||
4608 | } | ||
4609 | } | ||
4610 | } | ||
4543 | } | 4611 | } |
4544 | 4612 | ||
4545 | static void l2cap_handle_rej(struct l2cap_chan *chan, | 4613 | static void l2cap_handle_rej(struct l2cap_chan *chan, |