Skip to content

Commit

Permalink
igc: Refactor Rx timestamp handling
Browse files Browse the repository at this point in the history
Refactor the Rx timestamp handling in preparation to land
XDP support.

Rx timestamps are put in the Rx buffer by hardware, before the packet
data. When creating the xdp buffer, we will need to check the Rx
descriptor to determine if the buffer contains timestamp information
and consider the offset when setting xdp.data.

The Rx descriptor check is already done in igc_construct_skb(). To
avoid code duplication, this patch moves the timestamp handling to
igc_clean_rx_irq() so both skb and xdp paths can reuse it.

Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Signed-off-by: Vedang Patel <vedang.patel@intel.com>
Signed-off-by: Jithu Joseph <jithu.joseph@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Tested-by: Dvora Fuxbrumer <dvorax.fuxbrumer@linux.intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
  • Loading branch information
Andre Guedes authored and Tony Nguyen committed Mar 29, 2021
1 parent a39f5e5 commit e1ed4f9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 24 deletions.
3 changes: 1 addition & 2 deletions drivers/net/ethernet/intel/igc/igc.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,8 +547,7 @@ void igc_ptp_init(struct igc_adapter *adapter);
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);
Expand Down
30 changes: 20 additions & 10 deletions drivers/net/ethernet/intel/igc/igc_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1581,10 +1581,11 @@ static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring,

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;
Expand All @@ -1597,11 +1598,8 @@ static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring,
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;
Expand Down Expand Up @@ -1895,6 +1893,8 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
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 */
Expand All @@ -1916,14 +1916,24 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)

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) {
Expand Down
25 changes: 13 additions & 12 deletions drivers/net/ethernet/intel/igc/igc_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,20 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,

/**
* 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
Expand All @@ -178,9 +178,10 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
* 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) {
Expand All @@ -201,8 +202,8 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
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)
Expand Down

0 comments on commit e1ed4f9

Please sign in to comment.