/* return slow start threshold (required) */
        u32 (*ssthresh)(struct sock *sk);
        /* lower bound for congestion window (optional) */
-       u32 (*min_cwnd)(struct sock *sk);
+       u32 (*min_cwnd)(const struct sock *sk);
        /* do new cwnd calculation (required) */
        void (*cong_avoid)(struct sock *sk, u32 ack,
                           u32 rtt, u32 in_flight, int good_ack);
 extern u32 tcp_reno_ssthresh(struct sock *sk);
 extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack,
                                u32 rtt, u32 in_flight, int flag);
-extern u32 tcp_reno_min_cwnd(struct sock *sk);
+extern u32 tcp_reno_min_cwnd(const struct sock *sk);
 extern struct tcp_congestion_ops tcp_reno;
 
 static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
 
        return max(tp->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       return tp->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
        if (new_state == TCP_CA_Loss)
        .cong_avoid     = bictcp_cong_avoid,
        .set_state      = bictcp_state,
        .undo_cwnd      = bictcp_undo_cwnd,
-       .min_cwnd       = bictcp_min_cwnd,
        .pkts_acked     = bictcp_acked,
        .owner          = THIS_MODULE,
        .name           = "bic",
 
        .init           = tcp_compound_init,
        .ssthresh       = tcp_reno_ssthresh,
        .cong_avoid     = tcp_compound_cong_avoid,
-       .min_cwnd       = tcp_reno_min_cwnd,
        .rtt_sample     = tcp_compound_rtt_calc,
        .set_state      = tcp_compound_state,
        .cwnd_event     = tcp_compound_cwnd_event,
 
        int ret = 0;
 
        /* all algorithms must implement ssthresh and cong_avoid ops */
-       if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+       if (!ca->ssthresh || !ca->cong_avoid) {
                printk(KERN_ERR "TCP %s does not implement required ops\n",
                       ca->name);
                return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
 
-/* Lower bound on congestion window. */
-u32 tcp_reno_min_cwnd(struct sock *sk)
+/* Lower bound on congestion window with halving. */
+u32 tcp_reno_min_cwnd(const struct sock *sk)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        return tp->snd_ssthresh/2;
 
        return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-       return tcp_sk(sk)->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
        if (new_state == TCP_CA_Loss)
        .cong_avoid     = bictcp_cong_avoid,
        .set_state      = bictcp_state,
        .undo_cwnd      = bictcp_undo_cwnd,
-       .min_cwnd       = bictcp_min_cwnd,
        .pkts_acked     = bictcp_acked,
        .owner          = THIS_MODULE,
        .name           = "cubic",
 
        }
 }
 
-/* Lower bound on congestion window. */
-static u32 htcp_min_cwnd(struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       return tp->snd_ssthresh;
-}
-
-
 static void htcp_init(struct sock *sk)
 {
        struct htcp *ca = inet_csk_ca(sk);
 static struct tcp_congestion_ops htcp = {
        .init           = htcp_init,
        .ssthresh       = htcp_recalc_ssthresh,
-       .min_cwnd       = htcp_min_cwnd,
        .cong_avoid     = htcp_cong_avoid,
        .set_state      = htcp_state,
        .undo_cwnd      = htcp_cwnd_undo,
 
        tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
+/* Lower bound on congestion window is slow start threshold
+ * unless congestion avoidance choice decides to overide it.
+ */
+static inline u32 tcp_cwnd_min(const struct sock *sk)
+{
+       const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
+
+       return ca_ops->min_cwnd ? ca_ops->min_cwnd(sk) : tcp_sk(sk)->snd_ssthresh;
+}
+
 /* Decrease cwnd each second ack. */
 static void tcp_cwnd_down(struct sock *sk)
 {
-       const struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        int decr = tp->snd_cwnd_cnt + 1;
 
        tp->snd_cwnd_cnt = decr&1;
        decr >>= 1;
 
-       if (decr && tp->snd_cwnd > icsk->icsk_ca_ops->min_cwnd(sk))
+       if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
                tp->snd_cwnd -= decr;
 
        tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
 
                return max(tp->snd_cwnd >> 1U, 2U);
 }
 
-static u32 tcp_veno_min_cwnd(struct sock * sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       return tp->snd_ssthresh;
-}
-
 static struct tcp_congestion_ops tcp_veno = {
        .init           = tcp_veno_init,
        .ssthresh       = tcp_veno_ssthresh,
        .cong_avoid     = tcp_veno_cong_avoid,
-       .min_cwnd       = tcp_veno_min_cwnd,
        .rtt_sample     = tcp_veno_rtt_calc,
        .set_state      = tcp_veno_state,
        .cwnd_event     = tcp_veno_cwnd_event,
 
        return w->cumul_ack;
 }
 
-static inline u32 westwood_bw_rttmin(const struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       const struct westwood *w = inet_csk_ca(sk);
-       return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
-}
 
 /*
  * TCP Westwood
  * in packets we use mss_cache). Rttmin is guaranteed to be >= 2
  * so avoids ever returning 0.
  */
-static u32 tcp_westwood_cwnd_min(struct sock *sk)
+static u32 tcp_westwood_bw_rttmin(const struct sock *sk)
 {
-       return westwood_bw_rttmin(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
+       const struct westwood *w = inet_csk_ca(sk);
+       return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
 }
 
 static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
                break;
 
        case CA_EVENT_COMPLETE_CWR:
-               tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(sk);
+               tp->snd_cwnd = tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
                break;
 
        case CA_EVENT_FRTO:
-               tp->snd_ssthresh = westwood_bw_rttmin(sk);
+               tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
                break;
 
        case CA_EVENT_SLOW_ACK:
        .init           = tcp_westwood_init,
        .ssthresh       = tcp_reno_ssthresh,
        .cong_avoid     = tcp_reno_cong_avoid,
-       .min_cwnd       = tcp_westwood_cwnd_min,
+       .min_cwnd       = tcp_westwood_bw_rttmin,
        .cwnd_event     = tcp_westwood_event,
        .get_info       = tcp_westwood_info,
        .pkts_acked     = tcp_westwood_pkts_acked,