void igc_ptp_reset(struct igc_adapter *adapter);
void igc_ptp_suspend(struct igc_adapter *adapter);
void igc_ptp_stop(struct igc_adapter *adapter);
-void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
- struct sk_buff *skb);
+ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
void igc_ptp_tx_hang(struct igc_adapter *adapter);
static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring,
struct igc_rx_buffer *rx_buffer,
- union igc_adv_rx_desc *rx_desc,
- unsigned int size)
+ unsigned int size, int pkt_offset,
+ ktime_t timestamp)
{
- void *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
+ void *va = page_address(rx_buffer->page) + rx_buffer->page_offset +
+ pkt_offset;
unsigned int truesize = igc_get_rx_frame_truesize(rx_ring, size);
unsigned int headlen;
struct sk_buff *skb;
if (unlikely(!skb))
return NULL;
- if (unlikely(igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP))) {
- igc_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
- va += IGC_TS_HDR_LEN;
- size -= IGC_TS_HDR_LEN;
- }
+ if (timestamp)
+ skb_hwtstamps(skb)->hwtstamp = timestamp;
/* Determine available headroom for copy */
headlen = size;
while (likely(total_packets < budget)) {
union igc_adv_rx_desc *rx_desc;
struct igc_rx_buffer *rx_buffer;
+ ktime_t timestamp = 0;
+ int pkt_offset = 0;
unsigned int size;
/* return some buffers to hardware, one at a time is too slow */
rx_buffer = igc_get_rx_buffer(rx_ring, size);
+ if (igc_test_staterr(rx_desc, IGC_RXDADV_STAT_TSIP)) {
+ void *pktbuf = page_address(rx_buffer->page) +
+ rx_buffer->page_offset;
+
+ timestamp = igc_ptp_rx_pktstamp(q_vector->adapter,
+ pktbuf);
+ pkt_offset = IGC_TS_HDR_LEN;
+ size -= IGC_TS_HDR_LEN;
+ }
+
/* retrieve a buffer from the ring */
if (skb)
igc_add_rx_frag(rx_ring, rx_buffer, skb, size);
else if (ring_uses_build_skb(rx_ring))
skb = igc_build_skb(rx_ring, rx_buffer, rx_desc, size);
else
- skb = igc_construct_skb(rx_ring, rx_buffer,
- rx_desc, size);
+ skb = igc_construct_skb(rx_ring, rx_buffer, size,
+ pkt_offset, timestamp);
/* exit if we failed to retrieve a buffer */
if (!skb) {
/**
* igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer
- * @q_vector: Pointer to interrupt specific structure
- * @va: Pointer to address containing Rx buffer
- * @skb: Buffer containing timestamp and packet
+ * @adapter: Pointer to adapter the packet buffer belongs to
+ * @buf: Pointer to packet buffer
*
* This function retrieves the timestamp saved in the beginning of packet
* buffer. While two timestamps are available, one in timer0 reference and the
* other in timer1 reference, this function considers only the timestamp in
* timer0 reference.
+ *
+ * Returns timestamp value.
*/
-void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
- struct sk_buff *skb)
+ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf)
{
- struct igc_adapter *adapter = q_vector->adapter;
- u64 regval;
+ ktime_t timestamp;
+ u32 secs, nsecs;
int adjust;
/* Timestamps are saved in little endian at the beginning of the packet
* SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds
* part of the timestamp.
*/
- regval = le32_to_cpu(va[2]);
- regval |= (u64)le32_to_cpu(va[3]) << 32;
- igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
+ nsecs = le32_to_cpu(buf[2]);
+ secs = le32_to_cpu(buf[3]);
+
+ timestamp = ktime_set(secs, nsecs);
/* Adjust timestamp for the RX latency based on link speed */
switch (adapter->link_speed) {
netdev_warn_once(adapter->netdev, "Imprecise timestamp\n");
break;
}
- skb_hwtstamps(skb)->hwtstamp =
- ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust);
+
+ return ktime_sub_ns(timestamp, adjust);
}
static void igc_ptp_disable_rx_timestamp(struct igc_adapter *adapter)