return removed ? 0 : -1;
 }
 
+static void cpts_purge_txq(struct cpts *cpts)
+{
+       struct cpts_skb_cb_data *skb_cb;
+       struct sk_buff *skb, *tmp;
+       int removed = 0;
+
+       skb_queue_walk_safe(&cpts->txq, skb, tmp) {
+               skb_cb = (struct cpts_skb_cb_data *)skb->cb;
+               if (time_after(jiffies, skb_cb->tmo)) {
+                       __skb_unlink(skb, &cpts->txq);
+                       dev_consume_skb_any(skb);
+                       ++removed;
+               }
+       }
+
+       if (removed)
+               dev_dbg(cpts->dev, "txq cleaned up %d\n", removed);
+}
+
 static bool cpts_match_tx_ts(struct cpts *cpts, struct cpts_event *event)
 {
        struct sk_buff *skb, *tmp;
        spin_lock_irqsave(&cpts->lock, flags);
        ts = ns_to_timespec64(timecounter_read(&cpts->tc));
 
-       if (!skb_queue_empty(&cpts->txq))
-               delay = CPTS_SKB_TX_WORK_TIMEOUT;
+       if (!skb_queue_empty(&cpts->txq)) {
+               cpts_purge_txq(cpts);
+               if (!skb_queue_empty(&cpts->txq))
+                       delay = CPTS_SKB_TX_WORK_TIMEOUT;
+       }
        spin_unlock_irqrestore(&cpts->lock, flags);
 
        pr_debug("cpts overflow check at %lld.%09ld\n",