Bluetooth: Add timer to Acknowledge I-frames
authorGustavo F. Padovan <padovan@profusion.mobi>
Sat, 1 May 2010 19:15:39 +0000 (16:15 -0300)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 10 May 2010 07:28:48 +0000 (09:28 +0200)
We ack I-frames on each txWindow/5 I-frames received, but if the sender
stop to send I-frames and it's not a txWindow multiple we can leave some
frames unacked.
So I added a timer to ack I-frames on this case. The timer expires in
200ms.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/l2cap.h
net/bluetooth/l2cap.c

index d9c20c3d6f3dd93fdd698ca5d9fd1b2dbdc50f87..48f10f46c73d5be5e4f7321dd24216847f09194b 100644 (file)
@@ -35,6 +35,7 @@
 #define L2CAP_DEFAULT_RETRANS_TO       1000    /* 1 second */
 #define L2CAP_DEFAULT_MONITOR_TO       12000   /* 12 seconds */
 #define L2CAP_DEFAULT_MAX_PDU_SIZE     672
+#define L2CAP_DEFAULT_ACK_TO           200
 
 #define L2CAP_CONN_TIMEOUT     (40000) /* 40 seconds */
 #define L2CAP_INFO_TIMEOUT     (4000)  /*  4 seconds */
@@ -348,6 +349,7 @@ struct l2cap_pinfo {
 
        struct timer_list       retrans_timer;
        struct timer_list       monitor_timer;
+       struct timer_list       ack_timer;
        struct sk_buff_head     tx_queue;
        struct sk_buff_head     srej_queue;
        struct srej_list        srej_l;
@@ -382,6 +384,8 @@ struct l2cap_pinfo {
                jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
 #define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \
                jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
+#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \
+               jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
 
 static inline int l2cap_tx_window_full(struct sock *sk)
 {
index f3869857ee9f82a9b6e85829a8dcf9493cd0012c..03006568f8a197c1790320d80184286204c02e34 100644 (file)
@@ -2235,6 +2235,15 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
        *ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
+static void l2cap_ack_timeout(unsigned long arg)
+{
+       struct sock *sk = (void *) arg;
+
+       bh_lock_sock(sk);
+       l2cap_send_ack(l2cap_pi(sk));
+       bh_unlock_sock(sk);
+}
+
 static inline void l2cap_ertm_init(struct sock *sk)
 {
        l2cap_pi(sk)->expected_ack_seq = 0;
@@ -2247,6 +2256,8 @@ static inline void l2cap_ertm_init(struct sock *sk)
                        l2cap_retrans_timeout, (unsigned long) sk);
        setup_timer(&l2cap_pi(sk)->monitor_timer,
                        l2cap_monitor_timeout, (unsigned long) sk);
+       setup_timer(&l2cap_pi(sk)->ack_timer,
+                       l2cap_ack_timeout, (unsigned long) sk);
 
        __skb_queue_head_init(SREJ_QUEUE(sk));
 }
@@ -2975,6 +2986,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
                skb_queue_purge(SREJ_QUEUE(sk));
                del_timer(&l2cap_pi(sk)->retrans_timer);
                del_timer(&l2cap_pi(sk)->monitor_timer);
+               del_timer(&l2cap_pi(sk)->ack_timer);
        }
 
        l2cap_chan_del(sk, ECONNRESET);
@@ -3005,6 +3017,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
                skb_queue_purge(SREJ_QUEUE(sk));
                del_timer(&l2cap_pi(sk)->retrans_timer);
                del_timer(&l2cap_pi(sk)->monitor_timer);
+               del_timer(&l2cap_pi(sk)->ack_timer);
        }
 
        l2cap_chan_del(sk, 0);
@@ -3484,6 +3497,8 @@ expected:
        if (err < 0)
                return err;
 
+       __mod_ack_timer();
+
        pi->num_to_ack = (pi->num_to_ack + 1) % L2CAP_DEFAULT_NUM_TO_ACK;
        if (pi->num_to_ack == L2CAP_DEFAULT_NUM_TO_ACK - 1)
                l2cap_send_ack(pi);