sfc: support separate PTP and general timestamping
Support MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_V2. Extract general timestamp corrections in addition to PTP corrections. Apply receive timestamp corrections for general datapath receive timestamping, and correspondingly for transmit. Signed-off-by: Laurence Evans <levans@solarflare.com> Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c4f64fcc4d
commit
04796f4c4d
|
@ -237,10 +237,17 @@ struct efx_ptp_timeset {
|
||||||
* @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time
|
* @ns_to_nic_time: Function to convert from scalar nanoseconds to NIC time
|
||||||
* @nic_to_kernel_time: Function to convert from NIC to kernel time
|
* @nic_to_kernel_time: Function to convert from NIC to kernel time
|
||||||
* @min_synchronisation_ns: Minimum acceptable corrected sync window
|
* @min_synchronisation_ns: Minimum acceptable corrected sync window
|
||||||
* @ts_corrections.tx: Required driver correction of transmit timestamps
|
* @capabilities: Capabilities flags from the NIC
|
||||||
* @ts_corrections.rx: Required driver correction of receive timestamps
|
* @ts_corrections.ptp_tx: Required driver correction of PTP packet transmit
|
||||||
|
* timestamps
|
||||||
|
* @ts_corrections.ptp_rx: Required driver correction of PTP packet receive
|
||||||
|
* timestamps
|
||||||
* @ts_corrections.pps_out: PPS output error (information only)
|
* @ts_corrections.pps_out: PPS output error (information only)
|
||||||
* @ts_corrections.pps_in: Required driver correction of PPS input timestamps
|
* @ts_corrections.pps_in: Required driver correction of PPS input timestamps
|
||||||
|
* @ts_corrections.general_tx: Required driver correction of general packet
|
||||||
|
* transmit timestamps
|
||||||
|
* @ts_corrections.general_rx: Required driver correction of general packet
|
||||||
|
* receive timestamps
|
||||||
* @evt_frags: Partly assembled PTP events
|
* @evt_frags: Partly assembled PTP events
|
||||||
* @evt_frag_idx: Current fragment number
|
* @evt_frag_idx: Current fragment number
|
||||||
* @evt_code: Last event code
|
* @evt_code: Last event code
|
||||||
|
@ -291,10 +298,12 @@ struct efx_ptp_data {
|
||||||
s32 correction);
|
s32 correction);
|
||||||
unsigned int min_synchronisation_ns;
|
unsigned int min_synchronisation_ns;
|
||||||
struct {
|
struct {
|
||||||
s32 tx;
|
s32 ptp_tx;
|
||||||
s32 rx;
|
s32 ptp_rx;
|
||||||
s32 pps_out;
|
s32 pps_out;
|
||||||
s32 pps_in;
|
s32 pps_in;
|
||||||
|
s32 general_tx;
|
||||||
|
s32 general_rx;
|
||||||
} ts_corrections;
|
} ts_corrections;
|
||||||
efx_qword_t evt_frags[MAX_EVENT_FRAGS];
|
efx_qword_t evt_frags[MAX_EVENT_FRAGS];
|
||||||
int evt_frag_idx;
|
int evt_frag_idx;
|
||||||
|
@ -537,11 +546,13 @@ ktime_t efx_ptp_nic_to_kernel_time(struct efx_tx_queue *tx_queue)
|
||||||
if (efx_ptp_use_mac_tx_timestamps(efx))
|
if (efx_ptp_use_mac_tx_timestamps(efx))
|
||||||
kt = efx_ptp_mac_s27_to_ktime_correction(efx,
|
kt = efx_ptp_mac_s27_to_ktime_correction(efx,
|
||||||
tx_queue->completed_timestamp_major,
|
tx_queue->completed_timestamp_major,
|
||||||
tx_queue->completed_timestamp_minor, 0);
|
tx_queue->completed_timestamp_minor,
|
||||||
|
ptp->ts_corrections.general_tx);
|
||||||
else
|
else
|
||||||
kt = ptp->nic_to_kernel_time(
|
kt = ptp->nic_to_kernel_time(
|
||||||
tx_queue->completed_timestamp_major,
|
tx_queue->completed_timestamp_major,
|
||||||
tx_queue->completed_timestamp_minor, 0);
|
tx_queue->completed_timestamp_minor,
|
||||||
|
ptp->ts_corrections.general_tx);
|
||||||
return kt;
|
return kt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,8 +617,9 @@ static int efx_ptp_get_attributes(struct efx_nic *efx)
|
||||||
static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx)
|
static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS_LEN);
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_GET_TIMESTAMP_CORRECTIONS_LEN);
|
||||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN);
|
MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_V2_LEN);
|
||||||
int rc;
|
int rc;
|
||||||
|
size_t out_len;
|
||||||
|
|
||||||
/* Get the timestamp corrections from the NIC. If this operation is
|
/* Get the timestamp corrections from the NIC. If this operation is
|
||||||
* not supported (older NICs) then no correction is required.
|
* not supported (older NICs) then no correction is required.
|
||||||
|
@ -617,21 +629,37 @@ static int efx_ptp_get_timestamp_corrections(struct efx_nic *efx)
|
||||||
MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
|
MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
|
||||||
|
|
||||||
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
|
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
|
||||||
outbuf, sizeof(outbuf), NULL);
|
outbuf, sizeof(outbuf), &out_len);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
efx->ptp_data->ts_corrections.tx = MCDI_DWORD(outbuf,
|
efx->ptp_data->ts_corrections.ptp_tx = MCDI_DWORD(outbuf,
|
||||||
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_TRANSMIT);
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_TRANSMIT);
|
||||||
efx->ptp_data->ts_corrections.rx = MCDI_DWORD(outbuf,
|
efx->ptp_data->ts_corrections.ptp_rx = MCDI_DWORD(outbuf,
|
||||||
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_RECEIVE);
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_RECEIVE);
|
||||||
efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf,
|
efx->ptp_data->ts_corrections.pps_out = MCDI_DWORD(outbuf,
|
||||||
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_OUT);
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_OUT);
|
||||||
efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf,
|
efx->ptp_data->ts_corrections.pps_in = MCDI_DWORD(outbuf,
|
||||||
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_IN);
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_PPS_IN);
|
||||||
|
|
||||||
|
if (out_len >= MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_V2_LEN) {
|
||||||
|
efx->ptp_data->ts_corrections.general_tx = MCDI_DWORD(
|
||||||
|
outbuf,
|
||||||
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_V2_GENERAL_TX);
|
||||||
|
efx->ptp_data->ts_corrections.general_rx = MCDI_DWORD(
|
||||||
|
outbuf,
|
||||||
|
PTP_OUT_GET_TIMESTAMP_CORRECTIONS_V2_GENERAL_RX);
|
||||||
|
} else {
|
||||||
|
efx->ptp_data->ts_corrections.general_tx =
|
||||||
|
efx->ptp_data->ts_corrections.ptp_tx;
|
||||||
|
efx->ptp_data->ts_corrections.general_rx =
|
||||||
|
efx->ptp_data->ts_corrections.ptp_rx;
|
||||||
|
}
|
||||||
} else if (rc == -EINVAL) {
|
} else if (rc == -EINVAL) {
|
||||||
efx->ptp_data->ts_corrections.tx = 0;
|
efx->ptp_data->ts_corrections.ptp_tx = 0;
|
||||||
efx->ptp_data->ts_corrections.rx = 0;
|
efx->ptp_data->ts_corrections.ptp_rx = 0;
|
||||||
efx->ptp_data->ts_corrections.pps_out = 0;
|
efx->ptp_data->ts_corrections.pps_out = 0;
|
||||||
efx->ptp_data->ts_corrections.pps_in = 0;
|
efx->ptp_data->ts_corrections.pps_in = 0;
|
||||||
|
efx->ptp_data->ts_corrections.general_tx = 0;
|
||||||
|
efx->ptp_data->ts_corrections.general_rx = 0;
|
||||||
} else {
|
} else {
|
||||||
efx_mcdi_display_error(efx, MC_CMD_PTP, sizeof(inbuf), outbuf,
|
efx_mcdi_display_error(efx, MC_CMD_PTP, sizeof(inbuf), outbuf,
|
||||||
sizeof(outbuf), rc);
|
sizeof(outbuf), rc);
|
||||||
|
@ -998,7 +1026,7 @@ static void efx_ptp_xmit_skb_mc(struct efx_nic *efx, struct sk_buff *skb)
|
||||||
timestamps.hwtstamp = ptp_data->nic_to_kernel_time(
|
timestamps.hwtstamp = ptp_data->nic_to_kernel_time(
|
||||||
MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MAJOR),
|
MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MAJOR),
|
||||||
MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MINOR),
|
MCDI_DWORD(txtime, PTP_OUT_TRANSMIT_MINOR),
|
||||||
ptp_data->ts_corrections.tx);
|
ptp_data->ts_corrections.ptp_tx);
|
||||||
|
|
||||||
skb_tstamp_tx(skb, ×tamps);
|
skb_tstamp_tx(skb, ×tamps);
|
||||||
|
|
||||||
|
@ -1745,7 +1773,7 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
|
||||||
evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time(
|
evt->hwtimestamp = efx->ptp_data->nic_to_kernel_time(
|
||||||
EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA),
|
EFX_QWORD_FIELD(ptp->evt_frags[0], MCDI_EVENT_DATA),
|
||||||
EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA),
|
EFX_QWORD_FIELD(ptp->evt_frags[1], MCDI_EVENT_DATA),
|
||||||
ptp->ts_corrections.rx);
|
ptp->ts_corrections.ptp_rx);
|
||||||
evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS);
|
evt->expiry = jiffies + msecs_to_jiffies(PKT_EVENT_LIFETIME_MS);
|
||||||
list_add_tail(&evt->link, &ptp->evt_list);
|
list_add_tail(&evt->link, &ptp->evt_list);
|
||||||
|
|
||||||
|
@ -1908,7 +1936,7 @@ void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
|
||||||
timestamps->hwtstamp = efx_ptp_s27_to_ktime_correction(
|
timestamps->hwtstamp = efx_ptp_s27_to_ktime_correction(
|
||||||
pkt_timestamp_major,
|
pkt_timestamp_major,
|
||||||
pkt_timestamp_minor,
|
pkt_timestamp_minor,
|
||||||
efx->ptp_data->ts_corrections.rx);
|
efx->ptp_data->ts_corrections.general_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
|
static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
|
||||||
|
|
Loading…
Reference in New Issue