aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-05-17 23:53:41 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2012-06-04 23:34:03 -0400
commite31f76337257616aca0ea15abee271513b17426c (patch)
tree4817376d779766ff6a581aff8127f7126ccd6ada /net/bluetooth/l2cap_core.c
parent61aa4f5b9f43b21668aec51da2df3e9ed5f4226d (diff)
Bluetooth: Update l2cap_send_i_or_rr_or_rnr to fit the spec better
This action now exactly matches what is defined in the ERTM specification, including clearing the remote busy flag and setting the retransmit timer rather than retransmitting frames directly. The spec does not retransmit frames as part of this action, since retransmission is only triggered by REJ, SREJ, or an RR with the final bit set. struct l2cap_ctrl is also used to set up header values. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 8436806835e0..a7d96c937392 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1760,18 +1760,6 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
1760 return sent; 1760 return sent;
1761} 1761}
1762 1762
1763static int l2cap_retransmit_frames(struct l2cap_chan *chan)
1764{
1765 int ret;
1766
1767 if (!skb_queue_empty(&chan->tx_q))
1768 chan->tx_send_head = chan->tx_q.next;
1769
1770 chan->next_tx_seq = chan->expected_ack_seq;
1771 ret = l2cap_ertm_send(chan);
1772 return ret;
1773}
1774
1775static void l2cap_send_ack(struct l2cap_chan *chan) 1763static void l2cap_send_ack(struct l2cap_chan *chan)
1776{ 1764{
1777 struct l2cap_ctrl control; 1765 struct l2cap_ctrl control;
@@ -4195,25 +4183,35 @@ static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
4195 4183
4196static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) 4184static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
4197{ 4185{
4198 u32 control = 0; 4186 struct l2cap_ctrl control;
4199 4187
4200 chan->frames_sent = 0; 4188 BT_DBG("chan %p", chan);
4201 4189
4202 control |= __set_reqseq(chan, chan->buffer_seq); 4190 memset(&control, 0, sizeof(control));
4191 control.sframe = 1;
4192 control.final = 1;
4193 control.reqseq = chan->buffer_seq;
4194 set_bit(CONN_SEND_FBIT, &chan->conn_state);
4203 4195
4204 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { 4196 if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
4205 control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); 4197 control.super = L2CAP_SUPER_RNR;
4206 set_bit(CONN_RNR_SENT, &chan->conn_state); 4198 l2cap_send_sframe(chan, &control);
4207 } 4199 }
4208 4200
4209 if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state)) 4201 if (test_and_clear_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
4210 l2cap_retransmit_frames(chan); 4202 chan->unacked_frames > 0)
4203 __set_retrans_timer(chan);
4211 4204
4205 /* Send pending iframes */
4212 l2cap_ertm_send(chan); 4206 l2cap_ertm_send(chan);
4213 4207
4214 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) && 4208 if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
4215 chan->frames_sent == 0) { 4209 test_bit(CONN_SEND_FBIT, &chan->conn_state)) {
4216 control |= __set_ctrl_super(chan, L2CAP_SUPER_RR); 4210 /* F-bit wasn't sent in an s-frame or i-frame yet, so
4211 * send it now.
4212 */
4213 control.super = L2CAP_SUPER_RR;
4214 l2cap_send_sframe(chan, &control);
4217 } 4215 }
4218} 4216}
4219 4217