Skip to content

Commit a663726

Browse files
yemj-odcferruhy
authored andcommitted
net/ice: add frequency adjustment support for PTP
Add ice support for new ethdev API to adjust frequency for IEEE1588 PTP. Also, this patch reworks code for converting software update to hardware update. Signed-off-by: Simei Su <[email protected]> Signed-off-by: Mingjin Ye <[email protected]> Acked-by: Bruce Richardson <[email protected]>
1 parent 56e9319 commit a663726

File tree

4 files changed

+153
-48
lines changed

4 files changed

+153
-48
lines changed

doc/guides/nics/ice.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,22 @@ Forward Error Correction (FEC)
328328

329329
Supports get/set FEC mode and get FEC capability.
330330

331+
Time Synchronisation
332+
~~~~~~~~~~~~~~~~~~~~
333+
334+
The system operator can run a PTP (Precision Time Protocol) client application
335+
to synchronise the time on the network card (and optionally the time on the
336+
system) to the PTP master.
337+
338+
ICE PMD supports PTP client applications that use the DPDK IEEE1588 API to
339+
communicate with the PTP master clock. Note that PTP client application needs
340+
to run on PF and add the ``--force-max-simd-bitwidth=64`` startup parameter to
341+
disable vector mode.
342+
343+
.. code-block:: console
344+
345+
examples/dpdk-ptpclient -c f -n 3 -a 0000:ec:00.1 --force-max-simd-bitwidth=64 -- -T 1 -p 0x1 -c 1
346+
331347
Generic Flow Support
332348
~~~~~~~~~~~~~~~~~~~~
333349

drivers/net/ice/ice_ethdev.c

Lines changed: 132 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <sys/types.h>
1111
#include <sys/stat.h>
1212
#include <unistd.h>
13+
#include <math.h>
1314

1415
#include <rte_tailq.h>
1516
#include <rte_os_shim.h>
@@ -176,6 +177,7 @@ static int ice_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
176177
static int ice_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
177178
struct timespec *timestamp);
178179
static int ice_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta);
180+
static int ice_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm);
179181
static int ice_timesync_read_time(struct rte_eth_dev *dev,
180182
struct timespec *timestamp);
181183
static int ice_timesync_write_time(struct rte_eth_dev *dev,
@@ -307,6 +309,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
307309
.timesync_read_rx_timestamp = ice_timesync_read_rx_timestamp,
308310
.timesync_read_tx_timestamp = ice_timesync_read_tx_timestamp,
309311
.timesync_adjust_time = ice_timesync_adjust_time,
312+
.timesync_adjust_freq = ice_timesync_adjust_freq,
310313
.timesync_read_time = ice_timesync_read_time,
311314
.timesync_write_time = ice_timesync_write_time,
312315
.timesync_disable = ice_timesync_disable,
@@ -2332,6 +2335,33 @@ ice_get_supported_rxdid(struct ice_hw *hw)
23322335
return supported_rxdid;
23332336
}
23342337

2338+
static void ice_ptp_init_info(struct rte_eth_dev *dev)
2339+
{
2340+
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
2341+
struct ice_adapter *ad =
2342+
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2343+
2344+
switch (hw->phy_model) {
2345+
case ICE_PHY_ETH56G:
2346+
ad->ptp_tx_block = hw->pf_id;
2347+
ad->ptp_tx_index = 0;
2348+
break;
2349+
case ICE_PHY_E810:
2350+
case ICE_PHY_E830:
2351+
ad->ptp_tx_block = hw->port_info->lport;
2352+
ad->ptp_tx_index = 0;
2353+
break;
2354+
case ICE_PHY_E822:
2355+
ad->ptp_tx_block = hw->pf_id / ICE_PORTS_PER_QUAD;
2356+
ad->ptp_tx_index = (hw->pf_id % ICE_PORTS_PER_QUAD) *
2357+
ICE_PORTS_PER_PHY_E822 * ICE_QUADS_PER_PHY_E822;
2358+
break;
2359+
default:
2360+
PMD_DRV_LOG(WARNING, "Unsupported PHY model");
2361+
break;
2362+
}
2363+
}
2364+
23352365
static int
23362366
ice_dev_init(struct rte_eth_dev *dev)
23372367
{
@@ -2499,6 +2529,9 @@ ice_dev_init(struct rte_eth_dev *dev)
24992529
/* Initialize PHY model */
25002530
ice_ptp_init_phy_model(hw);
25012531

2532+
/* Initialize PTP info */
2533+
ice_ptp_init_info(dev);
2534+
25022535
if (hw->phy_model == ICE_PHY_E822) {
25032536
ret = ice_start_phy_timer_e822(hw, hw->pf_id);
25042537
if (ret)
@@ -6466,23 +6499,6 @@ ice_timesync_enable(struct rte_eth_dev *dev)
64666499
}
64676500
}
64686501

6469-
/* Initialize cycle counters for system time/RX/TX timestamp */
6470-
memset(&ad->systime_tc, 0, sizeof(struct rte_timecounter));
6471-
memset(&ad->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
6472-
memset(&ad->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
6473-
6474-
ad->systime_tc.cc_mask = ICE_CYCLECOUNTER_MASK;
6475-
ad->systime_tc.cc_shift = 0;
6476-
ad->systime_tc.nsec_mask = 0;
6477-
6478-
ad->rx_tstamp_tc.cc_mask = ICE_CYCLECOUNTER_MASK;
6479-
ad->rx_tstamp_tc.cc_shift = 0;
6480-
ad->rx_tstamp_tc.nsec_mask = 0;
6481-
6482-
ad->tx_tstamp_tc.cc_mask = ICE_CYCLECOUNTER_MASK;
6483-
ad->tx_tstamp_tc.cc_shift = 0;
6484-
ad->tx_tstamp_tc.nsec_mask = 0;
6485-
64866502
ad->ptp_ena = 1;
64876503

64886504
return 0;
@@ -6497,14 +6513,13 @@ ice_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
64976513
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
64986514
struct ice_rx_queue *rxq;
64996515
uint32_t ts_high;
6500-
uint64_t ts_ns, ns;
6516+
uint64_t ts_ns;
65016517

65026518
rxq = dev->data->rx_queues[flags];
65036519

65046520
ts_high = rxq->time_high;
65056521
ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1, ts_high);
6506-
ns = rte_timecounter_update(&ad->rx_tstamp_tc, ts_ns);
6507-
*timestamp = rte_ns_to_timespec(ns);
6522+
*timestamp = rte_ns_to_timespec(ts_ns);
65086523

65096524
return 0;
65106525
}
@@ -6516,51 +6531,127 @@ ice_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
65166531
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
65176532
struct ice_adapter *ad =
65186533
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
6519-
uint8_t lport;
6520-
uint64_t ts_ns, ns, tstamp;
6534+
uint64_t ts_ns, tstamp;
65216535
const uint64_t mask = 0xFFFFFFFF;
65226536
int ret;
65236537

6524-
lport = hw->port_info->lport;
6525-
6526-
ret = ice_read_phy_tstamp(hw, lport, 0, &tstamp);
6527-
if (ret) {
6538+
ret = ice_read_phy_tstamp(hw, ad->ptp_tx_block, ad->ptp_tx_index, &tstamp);
6539+
if (ret || tstamp == 0) {
65286540
PMD_DRV_LOG(ERR, "Failed to read phy timestamp");
65296541
return -1;
65306542
}
65316543

65326544
ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1, (tstamp >> 8) & mask);
6533-
ns = rte_timecounter_update(&ad->tx_tstamp_tc, ts_ns);
6534-
*timestamp = rte_ns_to_timespec(ns);
6545+
*timestamp = rte_ns_to_timespec(ts_ns);
65356546

65366547
return 0;
65376548
}
65386549

65396550
static int
65406551
ice_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
65416552
{
6542-
struct ice_adapter *ad =
6543-
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
6553+
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6554+
uint8_t tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
6555+
uint32_t lo, lo2, hi;
6556+
uint64_t time, ns;
6557+
int ret;
6558+
6559+
if (delta > INT32_MAX || delta < INT32_MIN) {
6560+
lo = ICE_READ_REG(hw, GLTSYN_TIME_L(tmr_idx));
6561+
hi = ICE_READ_REG(hw, GLTSYN_TIME_H(tmr_idx));
6562+
lo2 = ICE_READ_REG(hw, GLTSYN_TIME_L(tmr_idx));
6563+
6564+
if (lo2 < lo) {
6565+
lo = ICE_READ_REG(hw, GLTSYN_TIME_L(tmr_idx));
6566+
hi = ICE_READ_REG(hw, GLTSYN_TIME_H(tmr_idx));
6567+
}
6568+
6569+
time = ((uint64_t)hi << 32) | lo;
6570+
ns = time + delta;
6571+
6572+
wr32(hw, GLTSYN_SHTIME_L(tmr_idx), ICE_LO_DWORD(ns));
6573+
wr32(hw, GLTSYN_SHTIME_H(tmr_idx), ICE_HI_DWORD(ns));
6574+
wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
6575+
6576+
ret = ice_ptp_init_time(hw, ns, true);
6577+
if (ret) {
6578+
PMD_DRV_LOG(ERR, "PTP init time failed, err %d", ret);
6579+
return -1;
6580+
}
6581+
return 0;
6582+
}
6583+
6584+
ret = ice_ptp_adj_clock(hw, delta, true);
6585+
if (ret) {
6586+
PMD_DRV_LOG(ERR, "PTP adj clock failed, err %d", ret);
6587+
return -1;
6588+
}
6589+
6590+
return 0;
6591+
}
6592+
6593+
static int
6594+
ice_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm)
6595+
{
6596+
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6597+
int64_t incval, diff = 0;
6598+
bool negative = false;
6599+
uint64_t div, rem;
6600+
uint64_t divisor = 1000000ULL << 16;
6601+
int shift;
6602+
int ret;
6603+
6604+
incval = ice_get_base_incval(hw, ICE_SRC_TMR_MODE_NANOSECONDS);
6605+
6606+
if (ppm < 0) {
6607+
negative = true;
6608+
ppm = -ppm;
6609+
}
6610+
6611+
/* can incval * ppm overflow ? */
6612+
if (log2(incval) + log2(ppm) > 62) {
6613+
rem = ppm % divisor;
6614+
div = ppm / divisor;
6615+
diff = div * incval;
6616+
ppm = rem;
65446617

6545-
ad->systime_tc.nsec += delta;
6546-
ad->rx_tstamp_tc.nsec += delta;
6547-
ad->tx_tstamp_tc.nsec += delta;
6618+
shift = log2(incval) + log2(ppm) - 62;
6619+
if (shift > 0) {
6620+
/* drop precision */
6621+
ppm >>= shift;
6622+
divisor >>= shift;
6623+
}
6624+
}
6625+
6626+
if (divisor)
6627+
diff = diff + incval * ppm / divisor;
6628+
6629+
if (negative)
6630+
incval -= diff;
6631+
else
6632+
incval += diff;
65486633

6634+
ret = ice_ptp_write_incval_locked(hw, incval, true);
6635+
if (ret) {
6636+
PMD_DRV_LOG(ERR, "PTP failed to set incval, err %d", ret);
6637+
return -1;
6638+
}
65496639
return 0;
65506640
}
65516641

65526642
static int
65536643
ice_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
65546644
{
6555-
struct ice_adapter *ad =
6556-
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
6645+
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
65576646
uint64_t ns;
6647+
int ret;
65586648

65596649
ns = rte_timespec_to_ns(ts);
6560-
6561-
ad->systime_tc.nsec = ns;
6562-
ad->rx_tstamp_tc.nsec = ns;
6563-
ad->tx_tstamp_tc.nsec = ns;
6650+
ret = ice_ptp_init_time(hw, ns, true);
6651+
if (ret) {
6652+
PMD_DRV_LOG(ERR, "PTP init time failed, err %d", ret);
6653+
return -1;
6654+
}
65646655

65656656
return 0;
65666657
}
@@ -6569,11 +6660,9 @@ static int
65696660
ice_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
65706661
{
65716662
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
6572-
struct ice_adapter *ad =
6573-
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
65746663
uint8_t tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
65756664
uint32_t hi, lo, lo2;
6576-
uint64_t time, ns;
6665+
uint64_t time;
65776666

65786667
lo = ICE_READ_REG(hw, GLTSYN_TIME_L(tmr_idx));
65796668
hi = ICE_READ_REG(hw, GLTSYN_TIME_H(tmr_idx));
@@ -6585,8 +6674,7 @@ ice_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
65856674
}
65866675

65876676
time = ((uint64_t)hi << 32) | lo;
6588-
ns = rte_timecounter_update(&ad->systime_tc, time);
6589-
*ts = rte_ns_to_timespec(ns);
6677+
*ts = rte_ns_to_timespec(time);
65906678

65916679
return 0;
65926680
}

drivers/net/ice/ice_ethdev.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,9 +611,8 @@ struct ice_adapter {
611611
/* For vector PMD */
612612
eth_rx_burst_t tx_pkt_burst;
613613
/* For PTP */
614-
struct rte_timecounter systime_tc;
615-
struct rte_timecounter rx_tstamp_tc;
616-
struct rte_timecounter tx_tstamp_tc;
614+
uint8_t ptp_tx_block;
615+
uint8_t ptp_tx_index;
617616
bool ptp_ena;
618617
uint64_t time_hw;
619618
struct ice_fdir_prof_info fdir_prof_info[ICE_MAX_PTGS];

drivers/net/ice/ice_rxtx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3066,7 +3066,9 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
30663066
else if (ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)
30673067
cd_type_cmd_tso_mss |=
30683068
((uint64_t)ICE_TX_CTX_DESC_TSYN <<
3069-
ICE_TXD_CTX_QW1_CMD_S);
3069+
ICE_TXD_CTX_QW1_CMD_S) |
3070+
(((uint64_t)txq->vsi->adapter->ptp_tx_index <<
3071+
ICE_TXD_CTX_QW1_TSYN_S) & ICE_TXD_CTX_QW1_TSYN_M);
30703072

30713073
ctx_txd->tunneling_params =
30723074
rte_cpu_to_le_32(cd_tunneling_params);

0 commit comments

Comments
 (0)