ethdev: add namespace
[dpdk.git] / drivers / net / cnxk / cnxk_ptp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "cnxk_ethdev.h"
6
7 int
8 cnxk_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
9 {
10         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
11
12         /* This API returns the raw PTP HI clock value. Since LFs do not
13          * have direct access to PTP registers and it requires mbox msg
14          * to AF for this value. In fastpath reading this value for every
15          * packet (which involes mbox call) becomes very expensive, hence
16          * we should be able to derive PTP HI clock value from tsc by
17          * using freq_mult and clk_delta calculated during configure stage.
18          */
19         *clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
20
21         return 0;
22 }
23
24 /* This function calculates two parameters "clk_freq_mult" and
25  * "clk_delta" which is useful in deriving PTP HI clock from
26  * timestamp counter (tsc) value.
27  */
28 int
29 cnxk_nix_tsc_convert(struct cnxk_eth_dev *dev)
30 {
31         uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
32         struct roc_nix *nix = &dev->nix;
33         int rc, val;
34
35         /* Calculating the frequency at which PTP HI clock is running */
36         rc = roc_nix_ptp_clock_read(nix, &ticks_base, &tsc, false);
37         if (rc) {
38                 plt_err("Failed to read the raw clock value: %d", rc);
39                 goto fail;
40         }
41
42         rte_delay_ms(100);
43
44         rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, false);
45         if (rc) {
46                 plt_err("Failed to read the raw clock value: %d", rc);
47                 goto fail;
48         }
49
50         t_freq = (ticks - ticks_base) * 10;
51
52         /* Calculating the freq multiplier viz the ratio between the
53          * frequency at which PTP HI clock works and tsc clock runs
54          */
55         dev->clk_freq_mult =
56                 (double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
57
58         val = false;
59 #ifdef RTE_ARM_EAL_RDTSC_USE_PMU
60         val = true;
61 #endif
62         rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, val);
63         if (rc) {
64                 plt_err("Failed to read the raw clock value: %d", rc);
65                 goto fail;
66         }
67
68         /* Calculating delta between PTP HI clock and tsc */
69         dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
70
71 fail:
72         return rc;
73 }
74
75 int
76 cnxk_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
77 {
78         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
79         struct roc_nix *nix = &dev->nix;
80         uint64_t clock, ns;
81         int rc;
82
83         rc = roc_nix_ptp_clock_read(nix, &clock, NULL, false);
84         if (rc)
85                 return rc;
86
87         ns = rte_timecounter_update(&dev->systime_tc, clock);
88         *ts = rte_ns_to_timespec(ns);
89         return 0;
90 }
91
92 int
93 cnxk_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
94                              const struct timespec *ts)
95 {
96         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
97         uint64_t ns;
98
99         ns = rte_timespec_to_ns(ts);
100         /* Set the time counters to a new value. */
101         dev->systime_tc.nsec = ns;
102         dev->rx_tstamp_tc.nsec = ns;
103         dev->tx_tstamp_tc.nsec = ns;
104
105         return 0;
106 }
107
108 int
109 cnxk_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
110 {
111         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
112         struct roc_nix *nix = &dev->nix;
113         int rc;
114
115         /* Adjust the frequent to make tics increments in 10^9 tics per sec */
116         if (delta < ROC_NIX_PTP_FREQ_ADJUST &&
117             delta > -ROC_NIX_PTP_FREQ_ADJUST) {
118                 rc = roc_nix_ptp_sync_time_adjust(nix, delta);
119                 if (rc)
120                         return rc;
121
122                 /* Since the frequency of PTP comp register is tuned, delta and
123                  * freq mult calculation for deriving PTP_HI from timestamp
124                  * counter should be done again.
125                  */
126                 rc = cnxk_nix_tsc_convert(dev);
127                 if (rc)
128                         plt_err("Failed to calculate delta and freq mult");
129         }
130
131         dev->systime_tc.nsec += delta;
132         dev->rx_tstamp_tc.nsec += delta;
133         dev->tx_tstamp_tc.nsec += delta;
134
135         return 0;
136 }
137
138 int
139 cnxk_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
140                                     struct timespec *timestamp, uint32_t flags)
141 {
142         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
143         struct cnxk_timesync_info *tstamp = &dev->tstamp;
144         uint64_t ns;
145
146         PLT_SET_USED(flags);
147
148         if (!tstamp->rx_ready)
149                 return -EINVAL;
150
151         ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
152         *timestamp = rte_ns_to_timespec(ns);
153         tstamp->rx_ready = 0;
154         return 0;
155 }
156
157 int
158 cnxk_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
159                                     struct timespec *timestamp)
160 {
161         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
162         struct cnxk_timesync_info *tstamp = &dev->tstamp;
163         uint64_t ns;
164
165         if (*tstamp->tx_tstamp == 0)
166                 return -EINVAL;
167
168         ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
169         *timestamp = rte_ns_to_timespec(ns);
170         *tstamp->tx_tstamp = 0;
171         rte_wmb();
172
173         return 0;
174 }
175
176 int
177 cnxk_nix_timesync_enable(struct rte_eth_dev *eth_dev)
178 {
179         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
180         struct cnxk_timesync_info *tstamp = &dev->tstamp;
181         struct roc_nix *nix = &dev->nix;
182         const struct rte_memzone *ts;
183         int rc = 0;
184
185         /* If we are VF/SDP/LBK, ptp cannot not be enabled */
186         if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix)) {
187                 plt_err("PTP cannot be enabled for VF/SDP/LBK");
188                 return -EINVAL;
189         }
190
191         if (dev->ptp_en)
192                 return rc;
193
194         if (dev->ptype_disable) {
195                 plt_err("Ptype offload is disabled, it should be enabled");
196                 return -EINVAL;
197         }
198
199         if (dev->npc.switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
200                 plt_err("Both PTP and switch header cannot be enabled");
201                 return -EINVAL;
202         }
203
204         /* Allocating a iova address for tx tstamp */
205         ts = rte_eth_dma_zone_reserve(eth_dev, "cnxk_ts", 0, 128, 128, 0);
206         if (ts == NULL) {
207                 plt_err("Failed to allocate mem for tx tstamp addr");
208                 return -ENOMEM;
209         }
210
211         tstamp->tx_tstamp_iova = ts->iova;
212         tstamp->tx_tstamp = ts->addr;
213
214         rc = rte_mbuf_dyn_rx_timestamp_register(&tstamp->tstamp_dynfield_offset,
215                                                 &tstamp->rx_tstamp_dynflag);
216         if (rc) {
217                 plt_err("Failed to register Rx timestamp field/flag");
218                 goto error;
219         }
220
221         /* System time should be already on by default */
222         memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
223         memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
224         memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
225
226         dev->systime_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
227         dev->rx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
228         dev->tx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
229
230         dev->rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
231
232         rc = roc_nix_ptp_rx_ena_dis(nix, true);
233         if (!rc) {
234                 rc = roc_nix_ptp_tx_ena_dis(nix, true);
235                 if (rc) {
236                         roc_nix_ptp_rx_ena_dis(nix, false);
237                         goto error;
238                 }
239         }
240
241         rc = nix_recalc_mtu(eth_dev);
242         if (rc) {
243                 plt_err("Failed to set MTU size for ptp");
244                 goto error;
245         }
246
247         return rc;
248
249 error:
250         rte_eth_dma_zone_free(eth_dev, "cnxk_ts", 0);
251         dev->tstamp.tx_tstamp_iova = 0;
252         dev->tstamp.tx_tstamp = NULL;
253         return rc;
254 }
255
256 int
257 cnxk_nix_timesync_disable(struct rte_eth_dev *eth_dev)
258 {
259         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
260         uint64_t rx_offloads = RTE_ETH_RX_OFFLOAD_TIMESTAMP;
261         struct roc_nix *nix = &dev->nix;
262         int rc = 0;
263
264         /* If we are VF/SDP/LBK, ptp cannot not be disabled */
265         if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix))
266                 return -EINVAL;
267
268         if (!dev->ptp_en)
269                 return rc;
270
271         dev->rx_offloads &= ~rx_offloads;
272
273         rc = roc_nix_ptp_rx_ena_dis(nix, false);
274         if (!rc) {
275                 rc = roc_nix_ptp_tx_ena_dis(nix, false);
276                 if (rc) {
277                         roc_nix_ptp_rx_ena_dis(nix, true);
278                         return rc;
279                 }
280         }
281
282         rc = nix_recalc_mtu(eth_dev);
283         if (rc)
284                 plt_err("Failed to set MTU size for ptp");
285
286         return rc;
287 }