Commit fc9e5020 authored by Andre Guedes's avatar Andre Guedes Committed by Tony Nguyen

igc: Fix igc_ptp_rx_pktstamp()

The comment describing the timestamps layout in the packet buffer is
wrong and the code is actually retrieving the timestamp in Timer 1
reference instead of Timer 0. This hasn't been a big issue so far
because hardware is configured to report both timestamps using Timer 0
(see IGC_SRRCTL register configuration in igc_ptp_enable_rx_timestamp()
helper). This patch fixes the comment and the code so we retrieve the
timestamp in Timer 0 reference as expected.

This patch also takes the opportunity to get rid of the hw.mac.type check
since it is not required.

Fixes: 81b05520 ("igc: Add support for RX timestamping")
Signed-off-by: default avatarAndre Guedes <andre.guedes@intel.com>
Signed-off-by: default avatarVedang Patel <vedang.patel@intel.com>
Signed-off-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Reviewed-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Tested-by: default avatarDvora Fuxbrumer <dvorax.fuxbrumer@linux.intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 9a4a1cdc
...@@ -547,7 +547,7 @@ void igc_ptp_init(struct igc_adapter *adapter); ...@@ -547,7 +547,7 @@ void igc_ptp_init(struct igc_adapter *adapter);
void igc_ptp_reset(struct igc_adapter *adapter); void igc_ptp_reset(struct igc_adapter *adapter);
void igc_ptp_suspend(struct igc_adapter *adapter); void igc_ptp_suspend(struct igc_adapter *adapter);
void igc_ptp_stop(struct igc_adapter *adapter); void igc_ptp_stop(struct igc_adapter *adapter);
void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va, void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
struct sk_buff *skb); struct sk_buff *skb);
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); 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); int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
......
...@@ -152,32 +152,37 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter, ...@@ -152,32 +152,37 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,
} }
/** /**
* igc_ptp_rx_pktstamp - retrieve Rx per packet timestamp * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer
* @q_vector: Pointer to interrupt specific structure * @q_vector: Pointer to interrupt specific structure
* @va: Pointer to address containing Rx buffer * @va: Pointer to address containing Rx buffer
* @skb: Buffer containing timestamp and packet * @skb: Buffer containing timestamp and packet
* *
* This function is meant to retrieve the first timestamp from the * This function retrieves the timestamp saved in the beginning of packet
* first buffer of an incoming frame. The value is stored in little * buffer. While two timestamps are available, one in timer0 reference and the
* endian format starting on byte 0. There's a second timestamp * other in timer1 reference, this function considers only the timestamp in
* starting on byte 8. * timer0 reference.
**/ */
void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va, void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct igc_adapter *adapter = q_vector->adapter; struct igc_adapter *adapter = q_vector->adapter;
__le64 *regval = (__le64 *)va; u64 regval;
int adjust = 0; int adjust;
/* The timestamp is recorded in little endian format. /* Timestamps are saved in little endian at the beginning of the packet
* DWORD: | 0 | 1 | 2 | 3 * buffer following the layout:
* Field: | Timer0 Low | Timer0 High | Timer1 Low | Timer1 High *
* DWORD: | 0 | 1 | 2 | 3 |
* Field: | Timer1 SYSTIML | Timer1 SYSTIMH | Timer0 SYSTIML | Timer0 SYSTIMH |
*
* SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds
* part of the timestamp.
*/ */
igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval = le32_to_cpu(va[2]);
le64_to_cpu(regval[0])); regval |= (u64)le32_to_cpu(va[3]) << 32;
igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
/* adjust timestamp for the RX latency based on link speed */ /* Adjust timestamp for the RX latency based on link speed */
if (adapter->hw.mac.type == igc_i225) {
switch (adapter->link_speed) { switch (adapter->link_speed) {
case SPEED_10: case SPEED_10:
adjust = IGC_I225_RX_LATENCY_10; adjust = IGC_I225_RX_LATENCY_10;
...@@ -191,7 +196,10 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va, ...@@ -191,7 +196,10 @@ void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va,
case SPEED_2500: case SPEED_2500:
adjust = IGC_I225_RX_LATENCY_2500; adjust = IGC_I225_RX_LATENCY_2500;
break; break;
} default:
adjust = 0;
netdev_warn_once(adapter->netdev, "Imprecise timestamp\n");
break;
} }
skb_hwtstamps(skb)->hwtstamp = skb_hwtstamps(skb)->hwtstamp =
ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment