if (!sk)
                return;
 
-       skb = skb_clone(orig_skb, GFP_ATOMIC);
-       if (!skb)
-               return;
-
        if (hwtstamps) {
-               *skb_hwtstamps(skb) =
+               *skb_hwtstamps(orig_skb) =
                        *hwtstamps;
        } else {
                /*
                 * so keep the shared tx_flags and only
                 * store software time stamp
                 */
-               skb->tstamp = ktime_get_real();
+               orig_skb->tstamp = ktime_get_real();
        }
 
+       skb = skb_clone(orig_skb, GFP_ATOMIC);
+       if (!skb)
+               return;
+
        serr = SKB_EXT_ERR(skb);
        memset(serr, 0, sizeof(*serr));
        serr->ee.ee_errno = ENOMSG;
 
        }
 }
 
+static void __packet_set_timestamp(struct packet_sock *po, void *frame,
+                                  ktime_t tstamp)
+{
+       union tpacket_uhdr h;
+       struct timespec ts;
+
+       if (!ktime_to_timespec_cond(tstamp, &ts) ||
+           !sock_flag(&po->sk, SOCK_TIMESTAMPING_SOFTWARE))
+               return;
+
+       h.raw = frame;
+       switch (po->tp_version) {
+       case TPACKET_V1:
+               h.h1->tp_sec = ts.tv_sec;
+               h.h1->tp_usec = ts.tv_nsec / NSEC_PER_USEC;
+               break;
+       case TPACKET_V2:
+               h.h2->tp_sec = ts.tv_sec;
+               h.h2->tp_nsec = ts.tv_nsec;
+               break;
+       case TPACKET_V3:
+       default:
+               WARN(1, "TPACKET version not supported.\n");
+               BUG();
+       }
+
+       /* one flush is safe, as both fields always lie on the same cacheline */
+       flush_dcache_page(pgv_to_page(&h.h1->tp_sec));
+       smp_wmb();
+}
+
 static void *packet_lookup_frame(struct packet_sock *po,
                struct packet_ring_buffer *rb,
                unsigned int position,
                ph = skb_shinfo(skb)->destructor_arg;
                BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
                atomic_dec(&po->tx_ring.pending);
+               __packet_set_timestamp(po, ph, skb->tstamp);
                __packet_set_status(po, ph, TP_STATUS_AVAILABLE);
        }
 
        skb->dev = dev;
        skb->priority = po->sk.sk_priority;
        skb->mark = po->sk.sk_mark;
+       sock_tx_timestamp(&po->sk, &skb_shinfo(skb)->tx_flags);
        skb_shinfo(skb)->destructor_arg = ph.raw;
 
        switch (po->tp_version) {