(1) if (csk->lastack < ch->ack && ch->ack <= csk->nxtsnd){ what if lastack = 254 and nxtsnd = 4 and ack = 2???? (2) the call to drive_tx is commented out... hopefully you know that. (3) usable_win = csk->win - ((csk->nxtsnd - csk->lastack) % sequence_space(csk)); are you real sure this works in the presence of sequence number wrap???? 737 case CPT_ACK: 738 spin_lock_irqsave(&csk->cop_txlock, lock_flags); 739 if (csk->lastack < ch->ack && ch->ack <= csk->nxtsnd){ 740 csk->lastack = ch->ack; 741 csk->win = ch->win; 742 spin_unlock_irqrestore(&csk->cop_txlock, lock_flags); 743 //cop_drive_tx(sk); 744 #if COP_FCD_DEBUG 745 printk(KERN_ALERT "last ack received %x and RECEIVED WINDOW SIZE %x\n", 746 #endif 747 } 748 else 749 spin_unlock_irqrestore(&csk->cop_txlock, lock_flags); 750 kfree_skb(skb) (4) This section here needs to be a single locked section!! If your front end gets preempted after testing qlen but before dequeuing evil beyond belief can ensue (5) If line 300 EVER executes, it is PROOF that something has gone HORRIBLY WRONG --- It is a SUPREMELY BAD idea to silently ignore such situations.... Much better to printk then while (1); 292 spin_lock_irqsave(&csk->cop_txlock,flags); 293 usable_win = csk->win - ((csk->nxtsnd - csk->lastack) % sequence_space(csk)); 294 qlen = sk->sk_write_queue.qlen; 295 spin_unlock_irqrestore(&csk->cop_txlock,flags); 296 297 while(usable_win && qlen){ 298 skb = skb_dequeue(&sk->sk_write_queue); 299 if (!skb){ 300 err = -1; 301 break; 302 } 303 ch = skb->h.raw; 304 305 spin_lock_irqsave(&csk->cop_txlock,flags); 306 ch->seq = ++csk->nxtsnd; 307 if(csk->state == CPS_UAD) 308 csk->lastack++; 309 spin_unlock_irqrestore(&csk->cop_txlock,flags);