#define ccid2_pr_debug(format, a...)
 #endif
 
-static const int ccid2_seq_len = 128;
-
 #ifdef CONFIG_IP_DCCP_CCID2_DEBUG
 static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
 {
                        BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
                        BUG_ON(time_before(seqp->ccid2s_sent,
                                           prev->ccid2s_sent));
-                       BUG_ON(len > ccid2_seq_len);
 
                        seqp = prev;
                }
        do {
                seqp = seqp->ccid2s_prev;
                len++;
-               BUG_ON(len > ccid2_seq_len);
        } while (seqp != hctx->ccid2hctx_seqh);
 
-       BUG_ON(len != ccid2_seq_len);
        ccid2_pr_debug("total len=%d\n", len);
+       BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN);
 }
 #else
 #define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
 #endif
 
+static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
+                                gfp_t gfp)
+{
+       struct ccid2_seq *seqp;
+       int i;
+
+       /* check if we have space to preserve the pointer to the buffer */
+       if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) /
+                                       sizeof(struct ccid2_seq*)))
+               return -ENOMEM;
+
+       /* allocate buffer and initialize linked list */
+       seqp = kmalloc(sizeof(*seqp) * num, gfp);
+       if (seqp == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < (num - 1); i++) {
+               seqp[i].ccid2s_next = &seqp[i + 1];
+               seqp[i + 1].ccid2s_prev = &seqp[i];
+       }
+       seqp[num - 1].ccid2s_next = seqp;
+       seqp->ccid2s_prev = &seqp[num - 1];
+
+       /* This is the first allocation.  Initiate the head and tail.  */
+       if (hctx->ccid2hctx_seqbufc == 0)
+               hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp;
+       else {
+               /* link the existing list with the one we just created */
+               hctx->ccid2hctx_seqh->ccid2s_next = seqp;
+               seqp->ccid2s_prev = hctx->ccid2hctx_seqh;
+
+               hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1];
+               seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt;
+       }
+
+       /* store the original pointer to the buffer so we can free it */
+       hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp;
+       hctx->ccid2hctx_seqbufc++;
+
+       return 0;
+}
+
 static int ccid2_hc_tx_send_packet(struct sock *sk,
                                   struct sk_buff *skb, int len)
 {
 {
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
+       struct ccid2_seq *next;
        u64 seq;
 
        ccid2_hc_tx_check_sanity(hctx);
        hctx->ccid2hctx_seqh->ccid2s_seq   = seq;
        hctx->ccid2hctx_seqh->ccid2s_acked = 0;
        hctx->ccid2hctx_seqh->ccid2s_sent  = jiffies;
-       hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;
 
-       ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
-                      hctx->ccid2hctx_pipe);
+       next = hctx->ccid2hctx_seqh->ccid2s_next;
+       /* check if we need to alloc more space */
+       if (next == hctx->ccid2hctx_seqt) {
+               int rc;
 
-       if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) {
-               /* XXX allocate more space */
-               WARN_ON(1);
+               ccid2_pr_debug("allocating more space in history\n");
+               rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL);
+               BUG_ON(rc); /* XXX what do we do? */
+
+               next = hctx->ccid2hctx_seqh->ccid2s_next;
+               BUG_ON(next == hctx->ccid2hctx_seqt);
        }
+       hctx->ccid2hctx_seqh = next;
+
+       ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
+                      hctx->ccid2hctx_pipe);
 
        hctx->ccid2hctx_sent++;
 
 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 {
         struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
-       int seqcount = ccid2_seq_len;
-       int i;
 
        hctx->ccid2hctx_cwnd      = 1;
        /* Initialize ssthresh to infinity.  This means that we will exit the
         */
        hctx->ccid2hctx_ssthresh  = ~0;
        hctx->ccid2hctx_numdupack = 3;
+       hctx->ccid2hctx_seqbufc   = 0;
 
        /* XXX init ~ to window size... */
-       hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
-                                        seqcount, gfp_any());
-       if (hctx->ccid2hctx_seqbuf == NULL)
+       if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0)
                return -ENOMEM;
 
-       for (i = 0; i < (seqcount - 1); i++) {
-               hctx->ccid2hctx_seqbuf[i].ccid2s_next =
-                                       &hctx->ccid2hctx_seqbuf[i + 1];
-               hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev =
-                                       &hctx->ccid2hctx_seqbuf[i];
-       }
-       hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next =
-                                       hctx->ccid2hctx_seqbuf;
-       hctx->ccid2hctx_seqbuf->ccid2s_prev =
-                                       &hctx->ccid2hctx_seqbuf[seqcount - 1];
-
-       hctx->ccid2hctx_seqh     = hctx->ccid2hctx_seqbuf;
-       hctx->ccid2hctx_seqt     = hctx->ccid2hctx_seqh;
        hctx->ccid2hctx_sent     = 0;
        hctx->ccid2hctx_rto      = 3 * HZ;
        hctx->ccid2hctx_srtt     = -1;
 static void ccid2_hc_tx_exit(struct sock *sk)
 {
         struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
+       int i;
 
        ccid2_hc_tx_kill_rto_timer(sk);
-       kfree(hctx->ccid2hctx_seqbuf);
-       hctx->ccid2hctx_seqbuf = NULL;
+
+       for (i = 0; i < hctx->ccid2hctx_seqbufc; i++)
+               kfree(hctx->ccid2hctx_seqbuf[i]);
+       hctx->ccid2hctx_seqbufc = 0;
 }
 
 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)