extern void igb_ptp_reset(struct igb_adapter *adapter);
 extern void igb_ptp_tx_work(struct work_struct *work);
 extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                               union e1000_adv_rx_desc *rx_desc,
+extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
                                struct sk_buff *skb);
+extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                               unsigned char *va,
+                               struct sk_buff *skb);
+static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+                                      union e1000_adv_rx_desc *rx_desc,
+                                      struct sk_buff *skb)
+{
+       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+               igb_ptp_rx_pktstamp(q_vector, skb->data, skb);
+               skb_pull(skb, IGB_TS_HDR_LEN);
+       } else if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS)) {
+               igb_ptp_rx_rgtstamp(q_vector, skb);
+       }
+}
 extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
                                  struct ifreq *ifr, int cmd);
 #endif /* CONFIG_IGB_PTP */
 
        adapter->ptp_tx_skb = NULL;
 }
 
-void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                        union e1000_adv_rx_desc *rx_desc,
+/**
+ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
+ * @q_vector: Pointer to interrupt specific structure
+ * @va: Pointer to address containing Rx buffer
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the first buffer of an
+ * incoming frame.  The value is stored in little endian format starting on
+ * byte 8.
+ */
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                        unsigned char *va,
+                        struct sk_buff *skb)
+{
+       u64 *regval = (u64 *)va;
+
+       /*
+        * The timestamp is recorded in little endian format.
+        * DWORD: 0        1        2        3
+        * Field: Reserved Reserved SYSTIML  SYSTIMH
+        */
+       igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
+                                  le64_to_cpu(regval[1]));
+}
+
+/**
+ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
+ * @q_vector: Pointer to interrupt specific structure
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the internal registers
+ * of the adapter and store it in the skb.
+ */
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
                         struct sk_buff *skb)
 {
        struct igb_adapter *adapter = q_vector->adapter;
        struct e1000_hw *hw = &adapter->hw;
        u64 regval;
 
-       if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
-                                      E1000_RXDADV_STAT_TS))
-               return;
-
        /*
         * If this bit is set, then the RX registers contain the time stamp. No
         * other packet will be time stamped until we read these registers, so
         * If nothing went wrong, then it should have a shared tx_flags that we
         * can turn into a skb_shared_hwtstamps.
         */
-       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
-               u32 *stamp = (u32 *)skb->data;
-               regval = le32_to_cpu(*(stamp + 2));
-               regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
-               skb_pull(skb, IGB_TS_HDR_LEN);
-       } else {
-               if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
-                       return;
+       if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+               return;
 
-               regval = rd32(E1000_RXSTMPL);
-               regval |= (u64)rd32(E1000_RXSTMPH) << 32;
-       }
+       regval = rd32(E1000_RXSTMPL);
+       regval |= (u64)rd32(E1000_RXSTMPH) << 32;
 
        igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }