aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/l2cap_core.c70
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
1839static 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
1839static void l2cap_retransmit_all(struct l2cap_chan *chan, 1848static 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
2544static 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 */
2536static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) 2552static 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)
4539static void l2cap_handle_srej(struct l2cap_chan *chan, 4555static 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
4545static void l2cap_handle_rej(struct l2cap_chan *chan, 4613static void l2cap_handle_rej(struct l2cap_chan *chan,