Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[cascardo/linux.git] / net / sctp / transport.c
index 953c21e..4e45bb6 100644 (file)
@@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
        sctp_transport_put(transport);
 }
 
-/* Destroy the transport data structure.
- * Assumes there are no more users of this structure.
- */
-static void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy_rcu(struct rcu_head *head)
 {
-       SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+       struct sctp_transport *transport;
 
+       transport = container_of(head, struct sctp_transport, rcu);
        if (transport->asoc)
                sctp_association_put(transport->asoc);
 
@@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
        SCTP_DBG_OBJCNT_DEC(transport);
 }
 
+/* Destroy the transport data structure.
+ * Assumes there are no more users of this structure.
+ */
+static void sctp_transport_destroy(struct sctp_transport *transport)
+{
+       SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+
+       call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+}
+
 /* Start T3_rtx timer if it is not already running and update the heartbeat
  * timer.  This routine is called every time a DATA chunk is sent.
  */
@@ -331,7 +339,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
                 * 1/8, rto_alpha would be expressed as 3.
                 */
                tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
-                       + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta);
+                       + (((__u32)abs64((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta);
                tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
                        + (rtt >> net->sctp.rto_alpha);
        } else {
@@ -363,6 +371,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
        if (tp->rto > tp->asoc->rto_max)
                tp->rto = tp->asoc->rto_max;
 
+       sctp_max_rto(tp->asoc, tp);
        tp->rtt = rtt;
 
        /* Reset rto_pending so that a new RTT measurement is started when a
@@ -620,6 +629,7 @@ void sctp_transport_reset(struct sctp_transport *t)
        t->burst_limited = 0;
        t->ssthresh = asoc->peer.i.a_rwnd;
        t->rto = asoc->rto_initial;
+       sctp_max_rto(asoc, t);
        t->rtt = 0;
        t->srtt = 0;
        t->rttvar = 0;