xref: /f-stack/dpdk/drivers/net/octeontx2/otx2_ptp.c (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4 
5 #include <rte_ethdev_driver.h>
6 
7 #include "otx2_ethdev.h"
8 
9 #define PTP_FREQ_ADJUST (1 << 9)
10 
11 /* Function to enable ptp config for VFs */
12 void
otx2_nix_ptp_enable_vf(struct rte_eth_dev * eth_dev)13 otx2_nix_ptp_enable_vf(struct rte_eth_dev *eth_dev)
14 {
15 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
16 
17 	if (otx2_nix_recalc_mtu(eth_dev))
18 		otx2_err("Failed to set MTU size for ptp");
19 
20 	dev->scalar_ena = true;
21 	dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
22 
23 	/* Setting up the function pointers as per new offload flags */
24 	otx2_eth_set_rx_function(eth_dev);
25 	otx2_eth_set_tx_function(eth_dev);
26 }
27 
28 static uint16_t
nix_eth_ptp_vf_burst(void * queue,struct rte_mbuf ** mbufs,uint16_t pkts)29 nix_eth_ptp_vf_burst(void *queue, struct rte_mbuf **mbufs, uint16_t pkts)
30 {
31 	struct otx2_eth_rxq *rxq = queue;
32 	struct rte_eth_dev *eth_dev;
33 
34 	RTE_SET_USED(mbufs);
35 	RTE_SET_USED(pkts);
36 
37 	eth_dev = rxq->eth_dev;
38 	otx2_nix_ptp_enable_vf(eth_dev);
39 
40 	return 0;
41 }
42 
43 static int
nix_read_raw_clock(struct otx2_eth_dev * dev,uint64_t * clock,uint64_t * tsc,uint8_t is_pmu)44 nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
45 		   uint8_t is_pmu)
46 {
47 	struct otx2_mbox *mbox = dev->mbox;
48 	struct ptp_req *req;
49 	struct ptp_rsp *rsp;
50 	int rc;
51 
52 	req = otx2_mbox_alloc_msg_ptp_op(mbox);
53 	req->op = PTP_OP_GET_CLOCK;
54 	req->is_pmu = is_pmu;
55 	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
56 	if (rc)
57 		goto fail;
58 
59 	if (clock)
60 		*clock = rsp->clk;
61 	if (tsc)
62 		*tsc = rsp->tsc;
63 
64 fail:
65 	return rc;
66 }
67 
68 /* This function calculates two parameters "clk_freq_mult" and
69  * "clk_delta" which is useful in deriving PTP HI clock from
70  * timestamp counter (tsc) value.
71  */
72 int
otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev * dev)73 otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev)
74 {
75 	uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
76 	int rc, val;
77 
78 	/* Calculating the frequency at which PTP HI clock is running */
79 	rc = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
80 	if (rc) {
81 		otx2_err("Failed to read the raw clock value: %d", rc);
82 		goto fail;
83 	}
84 
85 	rte_delay_ms(100);
86 
87 	rc = nix_read_raw_clock(dev, &ticks, &tsc, false);
88 	if (rc) {
89 		otx2_err("Failed to read the raw clock value: %d", rc);
90 		goto fail;
91 	}
92 
93 	t_freq = (ticks - ticks_base) * 10;
94 
95 	/* Calculating the freq multiplier viz the ratio between the
96 	 * frequency at which PTP HI clock works and tsc clock runs
97 	 */
98 	dev->clk_freq_mult =
99 		(double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
100 
101 	val = false;
102 #ifdef RTE_ARM_EAL_RDTSC_USE_PMU
103 	val = true;
104 #endif
105 	rc = nix_read_raw_clock(dev, &ticks, &tsc, val);
106 	if (rc) {
107 		otx2_err("Failed to read the raw clock value: %d", rc);
108 		goto fail;
109 	}
110 
111 	/* Calculating delta between PTP HI clock and tsc */
112 	dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
113 
114 fail:
115 	return rc;
116 }
117 
118 static void
nix_start_timecounters(struct rte_eth_dev * eth_dev)119 nix_start_timecounters(struct rte_eth_dev *eth_dev)
120 {
121 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
122 
123 	memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
124 	memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
125 	memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
126 
127 	dev->systime_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
128 	dev->rx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
129 	dev->tx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
130 }
131 
132 static int
nix_ptp_config(struct rte_eth_dev * eth_dev,int en)133 nix_ptp_config(struct rte_eth_dev *eth_dev, int en)
134 {
135 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
136 	struct otx2_mbox *mbox = dev->mbox;
137 	uint8_t rc = -EINVAL;
138 
139 	if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
140 		return rc;
141 
142 	if (en) {
143 		/* Enable time stamping of sent PTP packets. */
144 		otx2_mbox_alloc_msg_nix_lf_ptp_tx_enable(mbox);
145 		rc = otx2_mbox_process(mbox);
146 		if (rc) {
147 			otx2_err("MBOX ptp tx conf enable failed: err %d", rc);
148 			return rc;
149 		}
150 		/* Enable time stamping of received PTP packets. */
151 		otx2_mbox_alloc_msg_cgx_ptp_rx_enable(mbox);
152 	} else {
153 		/* Disable time stamping of sent PTP packets. */
154 		otx2_mbox_alloc_msg_nix_lf_ptp_tx_disable(mbox);
155 		rc = otx2_mbox_process(mbox);
156 		if (rc) {
157 			otx2_err("MBOX ptp tx conf disable failed: err %d", rc);
158 			return rc;
159 		}
160 		/* Disable time stamping of received PTP packets. */
161 		otx2_mbox_alloc_msg_cgx_ptp_rx_disable(mbox);
162 	}
163 
164 	return otx2_mbox_process(mbox);
165 }
166 
167 int
otx2_eth_dev_ptp_info_update(struct otx2_dev * dev,bool ptp_en)168 otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en)
169 {
170 	struct otx2_eth_dev *otx2_dev = (struct otx2_eth_dev *)dev;
171 	struct rte_eth_dev *eth_dev;
172 	int i;
173 
174 	if (!dev)
175 		return -EINVAL;
176 
177 	eth_dev = otx2_dev->eth_dev;
178 	if (!eth_dev)
179 		return -EINVAL;
180 
181 	otx2_dev->ptp_en = ptp_en;
182 	for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
183 		struct otx2_eth_rxq *rxq = eth_dev->data->rx_queues[i];
184 		rxq->mbuf_initializer =
185 			otx2_nix_rxq_mbuf_setup(otx2_dev,
186 						eth_dev->data->port_id);
187 	}
188 	if (otx2_dev_is_vf(otx2_dev) && !(otx2_dev_is_sdp(otx2_dev)) &&
189 	    !(otx2_dev_is_lbk(otx2_dev))) {
190 		/* In case of VF, setting of MTU cant be done directly in this
191 		 * function as this is running as part of MBOX request(PF->VF)
192 		 * and MTU setting also requires MBOX message to be
193 		 * sent(VF->PF)
194 		 */
195 		eth_dev->rx_pkt_burst = nix_eth_ptp_vf_burst;
196 		rte_mb();
197 	}
198 
199 	return 0;
200 }
201 
202 int
otx2_nix_timesync_enable(struct rte_eth_dev * eth_dev)203 otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
204 {
205 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
206 	int i, rc = 0;
207 
208 	/* If we are VF/SDP/LBK, ptp cannot not be enabled */
209 	if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev)) {
210 		otx2_info("PTP cannot be enabled in case of VF/SDP/LBK");
211 		return -EINVAL;
212 	}
213 
214 	if (otx2_ethdev_is_ptp_en(dev)) {
215 		otx2_info("PTP mode is already enabled");
216 		return -EINVAL;
217 	}
218 
219 	if (!(dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)) {
220 		otx2_err("Ptype offload is disabled, it should be enabled");
221 		return -EINVAL;
222 	}
223 
224 	if (dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG) {
225 		otx2_err("Both PTP and switch header enabled");
226 		return -EINVAL;
227 	}
228 
229 	/* Allocating a iova address for tx tstamp */
230 	const struct rte_memzone *ts;
231 	ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
232 				      0, OTX2_ALIGN, OTX2_ALIGN,
233 				      dev->node);
234 	if (ts == NULL) {
235 		otx2_err("Failed to allocate mem for tx tstamp addr");
236 		return -ENOMEM;
237 	}
238 
239 	dev->tstamp.tx_tstamp_iova = ts->iova;
240 	dev->tstamp.tx_tstamp = ts->addr;
241 
242 	rc = rte_mbuf_dyn_rx_timestamp_register(
243 			&dev->tstamp.tstamp_dynfield_offset,
244 			&dev->tstamp.rx_tstamp_dynflag);
245 	if (rc != 0) {
246 		otx2_err("Failed to register Rx timestamp field/flag");
247 		return -rte_errno;
248 	}
249 
250 	/* System time should be already on by default */
251 	nix_start_timecounters(eth_dev);
252 
253 	dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
254 	dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
255 	dev->tx_offload_flags |= NIX_TX_OFFLOAD_TSTAMP_F;
256 
257 	rc = nix_ptp_config(eth_dev, 1);
258 	if (!rc) {
259 		for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
260 			struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
261 			otx2_nix_form_default_desc(txq);
262 		}
263 
264 		/* Setting up the function pointers as per new offload flags */
265 		otx2_eth_set_rx_function(eth_dev);
266 		otx2_eth_set_tx_function(eth_dev);
267 	}
268 
269 	rc = otx2_nix_recalc_mtu(eth_dev);
270 	if (rc)
271 		otx2_err("Failed to set MTU size for ptp");
272 
273 	return rc;
274 }
275 
276 int
otx2_nix_timesync_disable(struct rte_eth_dev * eth_dev)277 otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
278 {
279 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
280 	int i, rc = 0;
281 
282 	if (!otx2_ethdev_is_ptp_en(dev)) {
283 		otx2_nix_dbg("PTP mode is disabled");
284 		return -EINVAL;
285 	}
286 
287 	if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
288 		return -EINVAL;
289 
290 	dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
291 	dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
292 	dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
293 
294 	rc = nix_ptp_config(eth_dev, 0);
295 	if (!rc) {
296 		for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
297 			struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
298 			otx2_nix_form_default_desc(txq);
299 		}
300 
301 		/* Setting up the function pointers as per new offload flags */
302 		otx2_eth_set_rx_function(eth_dev);
303 		otx2_eth_set_tx_function(eth_dev);
304 	}
305 
306 	rc = otx2_nix_recalc_mtu(eth_dev);
307 	if (rc)
308 		otx2_err("Failed to set MTU size for ptp");
309 
310 	return rc;
311 }
312 
313 int
otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev * eth_dev,struct timespec * timestamp,uint32_t __rte_unused flags)314 otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
315 				    struct timespec *timestamp,
316 				    uint32_t __rte_unused flags)
317 {
318 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
319 	struct otx2_timesync_info *tstamp = &dev->tstamp;
320 	uint64_t ns;
321 
322 	if (!tstamp->rx_ready)
323 		return -EINVAL;
324 
325 	ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
326 	*timestamp = rte_ns_to_timespec(ns);
327 	tstamp->rx_ready = 0;
328 
329 	otx2_nix_dbg("rx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
330 		     (uint64_t)tstamp->rx_tstamp, (uint64_t)timestamp->tv_sec,
331 		     (uint64_t)timestamp->tv_nsec);
332 
333 	return 0;
334 }
335 
336 int
otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev * eth_dev,struct timespec * timestamp)337 otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
338 				    struct timespec *timestamp)
339 {
340 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
341 	struct otx2_timesync_info *tstamp = &dev->tstamp;
342 	uint64_t ns;
343 
344 	if (*tstamp->tx_tstamp == 0)
345 		return -EINVAL;
346 
347 	ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
348 	*timestamp = rte_ns_to_timespec(ns);
349 
350 	otx2_nix_dbg("tx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
351 		     *tstamp->tx_tstamp, (uint64_t)timestamp->tv_sec,
352 		     (uint64_t)timestamp->tv_nsec);
353 
354 	*tstamp->tx_tstamp = 0;
355 	rte_wmb();
356 
357 	return 0;
358 }
359 
360 int
otx2_nix_timesync_adjust_time(struct rte_eth_dev * eth_dev,int64_t delta)361 otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
362 {
363 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
364 	struct otx2_mbox *mbox = dev->mbox;
365 	struct ptp_req *req;
366 	struct ptp_rsp *rsp;
367 	int rc;
368 
369 	/* Adjust the frequent to make tics increments in 10^9 tics per sec */
370 	if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
371 		req = otx2_mbox_alloc_msg_ptp_op(mbox);
372 		req->op = PTP_OP_ADJFINE;
373 		req->scaled_ppm = delta;
374 
375 		rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
376 		if (rc)
377 			return rc;
378 		/* Since the frequency of PTP comp register is tuned, delta and
379 		 * freq mult calculation for deriving PTP_HI from timestamp
380 		 * counter should be done again.
381 		 */
382 		rc = otx2_nix_raw_clock_tsc_conv(dev);
383 		if (rc)
384 			otx2_err("Failed to calculate delta and freq mult");
385 	}
386 	dev->systime_tc.nsec += delta;
387 	dev->rx_tstamp_tc.nsec += delta;
388 	dev->tx_tstamp_tc.nsec += delta;
389 
390 	return 0;
391 }
392 
393 int
otx2_nix_timesync_write_time(struct rte_eth_dev * eth_dev,const struct timespec * ts)394 otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
395 			     const struct timespec *ts)
396 {
397 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
398 	uint64_t ns;
399 
400 	ns = rte_timespec_to_ns(ts);
401 	/* Set the time counters to a new value. */
402 	dev->systime_tc.nsec = ns;
403 	dev->rx_tstamp_tc.nsec = ns;
404 	dev->tx_tstamp_tc.nsec = ns;
405 
406 	return 0;
407 }
408 
409 int
otx2_nix_timesync_read_time(struct rte_eth_dev * eth_dev,struct timespec * ts)410 otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
411 {
412 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
413 	struct otx2_mbox *mbox = dev->mbox;
414 	struct ptp_req *req;
415 	struct ptp_rsp *rsp;
416 	uint64_t ns;
417 	int rc;
418 
419 	req = otx2_mbox_alloc_msg_ptp_op(mbox);
420 	req->op = PTP_OP_GET_CLOCK;
421 	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
422 	if (rc)
423 		return rc;
424 
425 	ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
426 	*ts = rte_ns_to_timespec(ns);
427 
428 	otx2_nix_dbg("PTP time read: %"PRIu64" .%09"PRIu64"",
429 		     (uint64_t)ts->tv_sec, (uint64_t)ts->tv_nsec);
430 
431 	return 0;
432 }
433 
434 
435 int
otx2_nix_read_clock(struct rte_eth_dev * eth_dev,uint64_t * clock)436 otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
437 {
438 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
439 
440 	/* This API returns the raw PTP HI clock value. Since LFs doesn't
441 	 * have direct access to PTP registers and it requires mbox msg
442 	 * to AF for this value. In fastpath reading this value for every
443 	 * packet (which involes mbox call) becomes very expensive, hence
444 	 * we should be able to derive PTP HI clock value from tsc by
445 	 * using freq_mult and clk_delta calculated during configure stage.
446 	 */
447 	*clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
448 
449 	return 0;
450 }
451