[Bluetooth] Read local version information on device init
[pandora-kernel.git] / net / dccp / ackvec.c
index b4ff14f..4d176d3 100644 (file)
@@ -81,15 +81,16 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
        if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
                return -1;
 
-       avr = dccp_ackvec_record_new();
-       if (avr == NULL)
-               return -1;
-
        dccp_timestamp(sk, &now);
        elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
 
-       if (elapsed_time != 0)
-               dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
+       if (elapsed_time != 0 &&
+           dccp_insert_option_elapsed_time(sk, skb, elapsed_time))
+               return -1;
+
+       avr = dccp_ackvec_record_new();
+       if (avr == NULL)
+               return -1;
 
        DCCP_SKB_CB(skb)->dccpd_opt_len += len;
 
@@ -141,14 +142,13 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
        struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority);
 
        if (av != NULL) {
-               av->dccpav_buf_head     =
-                       av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
+               av->dccpav_buf_head     = DCCP_MAX_ACKVEC_LEN - 1;
                av->dccpav_buf_ackno    = DCCP_MAX_SEQNO + 1;
                av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
                av->dccpav_ack_ptr      = 0;
                av->dccpav_time.tv_sec  = 0;
                av->dccpav_time.tv_usec = 0;
-               av->dccpav_sent_len     = av->dccpav_vec_len = 0;
+               av->dccpav_vec_len      = 0;
                INIT_LIST_HEAD(&av->dccpav_records);
        }
 
@@ -159,7 +159,17 @@ void dccp_ackvec_free(struct dccp_ackvec *av)
 {
        if (unlikely(av == NULL))
                return;
-       WARN_ON(!list_empty(&av->dccpav_records));
+
+       if (!list_empty(&av->dccpav_records)) {
+               struct dccp_ackvec_record *avr, *next;
+
+               list_for_each_entry_safe(avr, next, &av->dccpav_records,
+                                        dccpavr_node) {
+                       list_del_init(&avr->dccpavr_node);
+                       dccp_ackvec_record_delete(avr);
+               }
+       }
+
        kmem_cache_free(dccp_ackvec_slab, av);
 }
 
@@ -300,7 +310,6 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
        av->dccpav_buf_ackno = ackno;
        dccp_timestamp(sk, &av->dccpav_time);
 out:
-       dccp_pr_debug("");
        return 0;
 
 out_duplicate:
@@ -343,11 +352,13 @@ static void dccp_ackvec_throw_record(struct dccp_ackvec *av,
 {
        struct dccp_ackvec_record *next;
 
-       av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1;
-       if (av->dccpav_buf_tail == 0)
-               av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
-
-       av->dccpav_vec_len -= avr->dccpavr_sent_len;
+       /* sort out vector length */
+       if (av->dccpav_buf_head <= avr->dccpavr_ack_ptr)
+               av->dccpav_vec_len = avr->dccpavr_ack_ptr - av->dccpav_buf_head;
+       else
+               av->dccpav_vec_len = DCCP_MAX_ACKVEC_LEN - 1
+                                    - av->dccpav_buf_head
+                                    + avr->dccpavr_ack_ptr;
 
        /* free records */
        list_for_each_entry_safe_from(avr, next, &av->dccpav_records,
@@ -424,8 +435,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
                break;
 found:
                if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
-                       const u8 state = (*vector &
-                                         DCCP_ACKVEC_STATE_MASK) >> 6;
+                       const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
                        if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
 #ifdef CONFIG_IP_DCCP_DEBUG
                                struct dccp_sock *dp = dccp_sk(sk);
@@ -442,6 +452,7 @@ found:
                                              (unsigned long long)
                                              avr->dccpavr_ack_ackno);
                                dccp_ackvec_throw_record(av, avr);
+                               break;
                        }
                        /*
                         * If it wasn't received, continue scanning... we might