Skip to content

Commit

Permalink
Bluetooth: Refactor l2cap_send_ack
Browse files Browse the repository at this point in the history
The function now encapsulates more of the logic to either immediately
send an ack if the transmit window is over 75% full, or wait for the
ack timer to expire if the transmit window is not full enough.  It is
also able to push out waiting iframes that can carry an
acknowledgement.

Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
  • Loading branch information
Mat Martineau authored and Johan Hedberg committed Jun 5, 2012
1 parent f5dbb07 commit 0a0aba4
Showing 1 changed file with 43 additions and 17 deletions.
60 changes: 43 additions & 17 deletions net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1772,28 +1772,54 @@ static int l2cap_retransmit_frames(struct l2cap_chan *chan)
return ret;
}

static void __l2cap_send_ack(struct l2cap_chan *chan)
static void l2cap_send_ack(struct l2cap_chan *chan)
{
u32 control = 0;
struct l2cap_ctrl control;
u16 frames_to_ack = __seq_offset(chan, chan->buffer_seq,
chan->last_acked_seq);
int threshold;

control |= __set_reqseq(chan, chan->buffer_seq);
BT_DBG("chan %p last_acked_seq %d buffer_seq %d",
chan, chan->last_acked_seq, chan->buffer_seq);

if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR);
set_bit(CONN_RNR_SENT, &chan->conn_state);
return;
}
memset(&control, 0, sizeof(control));
control.sframe = 1;

if (l2cap_ertm_send(chan) > 0)
return;
if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
chan->rx_state == L2CAP_RX_STATE_RECV) {
__clear_ack_timer(chan);
control.super = L2CAP_SUPER_RNR;
control.reqseq = chan->buffer_seq;
l2cap_send_sframe(chan, &control);
} else {
if (!test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) {
l2cap_ertm_send(chan);
/* If any i-frames were sent, they included an ack */
if (chan->buffer_seq == chan->last_acked_seq)
frames_to_ack = 0;
}

control |= __set_ctrl_super(chan, L2CAP_SUPER_RR);
}
/* Ack now if the tx window is 3/4ths full.
* Calculate without mul or div
*/
threshold = chan->tx_win;
threshold += threshold << 1;
threshold >>= 2;

BT_DBG("frames_to_ack %d, threshold %d", (int)frames_to_ack,
threshold);

if (frames_to_ack >= threshold) {
__clear_ack_timer(chan);
control.super = L2CAP_SUPER_RR;
control.reqseq = chan->buffer_seq;
l2cap_send_sframe(chan, &control);
frames_to_ack = 0;
}

static void l2cap_send_ack(struct l2cap_chan *chan)
{
__clear_ack_timer(chan);
__l2cap_send_ack(chan);
if (frames_to_ack)
__set_ack_timer(chan);
}
}

static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
Expand Down Expand Up @@ -2539,7 +2565,7 @@ static void l2cap_ack_timeout(struct work_struct *work)

l2cap_chan_lock(chan);

__l2cap_send_ack(chan);
l2cap_send_ack(chan);

l2cap_chan_unlock(chan);

Expand Down

0 comments on commit 0a0aba4

Please sign in to comment.