Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Intel Corporation
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include "idpf_ptp.h"
7 : : #include "idpf_common_virtchnl.h"
8 : : #include "base/virtchnl2.h"
9 : :
10 : : static enum idpf_ptp_access
11 : : idpf_ptp_get_access(const struct idpf_adapter *adapter, uint32_t direct,
12 : : uint32_t mailbox)
13 : : {
14 : 0 : if (adapter->ptp->caps & direct)
15 : : return IDPF_PTP_DIRECT;
16 [ # # # # : 0 : else if (adapter->ptp->caps & mailbox)
# # # # #
# ]
17 : : return IDPF_PTP_MAILBOX;
18 : : else
19 : 0 : return IDPF_PTP_NONE;
20 : : }
21 : :
22 : : #define IDPF_PTP_ACCESS(adapter, cap) \
23 : : ((uint8_t)idpf_ptp_get_access((adapter), (cap), (cap##_MB)))
24 : :
25 : : static void
26 : 0 : idpf_ptp_get_features_access(const struct idpf_adapter *adapter)
27 : : {
28 [ # # ]: 0 : struct idpf_ptp *ptp = adapter->ptp;
29 : :
30 : 0 : ptp->get_dev_clk_time_access =
31 [ # # ]: 0 : IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME);
32 : 0 : ptp->get_cross_tstamp_access =
33 [ # # ]: 0 : IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_GET_CROSS_TIME);
34 : 0 : ptp->set_dev_clk_time_access =
35 [ # # ]: 0 : IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME);
36 : 0 : ptp->adj_dev_clk_time_access =
37 [ # # ]: 0 : IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK);
38 : 0 : ptp->tx_tstamp_access =
39 : 0 : IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_TX_TSTAMPS);
40 : 0 : }
41 : :
42 : : RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_get_caps)
43 : : int
44 : 0 : idpf_ptp_get_caps(struct idpf_adapter *adapter)
45 : : {
46 : : struct virtchnl2_ptp_cross_time_reg_offsets cross_tstamp_offsets;
47 : : struct virtchnl2_ptp_clk_adj_reg_offsets clk_adj_offsets;
48 : 0 : struct virtchnl2_ptp_get_caps send_ptp_caps_msg = {0};
49 : : struct virtchnl2_ptp_clk_reg_offsets clock_offsets;
50 : : struct virtchnl2_ptp_get_caps *recv_ptp_caps_msg;
51 : 0 : struct idpf_cmd_info args = {0};
52 : : struct idpf_ptp_secondary_mbx *scnd_mbx;
53 : 0 : struct idpf_ptp *ptp = adapter->ptp;
54 : : struct idpf_hw *hw = &adapter->hw;
55 : : enum idpf_ptp_access access_type;
56 : : int err;
57 : : uint32_t temp_offset;
58 : :
59 : 0 : send_ptp_caps_msg.caps = CPU_TO_LE32(VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME |
60 : : VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME_MB |
61 : : VIRTCHNL2_CAP_PTP_GET_CROSS_TIME |
62 : : VIRTCHNL2_CAP_PTP_GET_CROSS_TIME_MB |
63 : : VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME |
64 : : VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME_MB |
65 : : VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK |
66 : : VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK_MB |
67 : : VIRTCHNL2_CAP_PTP_TX_TSTAMPS |
68 : : VIRTCHNL2_CAP_PTP_TX_TSTAMPS_MB);
69 : :
70 : 0 : args.ops = VIRTCHNL2_OP_PTP_GET_CAPS;
71 : 0 : args.in_args = (uint8_t *)&send_ptp_caps_msg;
72 : 0 : args.in_args_size = sizeof(send_ptp_caps_msg);
73 : 0 : args.out_buffer = adapter->mbx_resp;
74 : 0 : args.out_size = sizeof(*recv_ptp_caps_msg);
75 : :
76 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
77 [ # # ]: 0 : if (err < 0)
78 : : return err;
79 : :
80 : 0 : recv_ptp_caps_msg = (struct virtchnl2_ptp_get_caps *)args.out_buffer;
81 : 0 : ptp->caps = LE32_TO_CPU(recv_ptp_caps_msg->caps);
82 : 0 : ptp->base_incval = LE64_TO_CPU(recv_ptp_caps_msg->base_incval);
83 : 0 : ptp->max_adj = LE32_TO_CPU(recv_ptp_caps_msg->max_adj);
84 : :
85 : : scnd_mbx = &ptp->secondary_mbx;
86 : 0 : scnd_mbx->peer_mbx_q_id = LE16_TO_CPU(recv_ptp_caps_msg->peer_mbx_q_id);
87 : 0 : scnd_mbx->valid = scnd_mbx->peer_mbx_q_id != 0xffff;
88 [ # # ]: 0 : if (scnd_mbx->valid)
89 : 0 : scnd_mbx->peer_id = recv_ptp_caps_msg->peer_id;
90 : :
91 : 0 : idpf_ptp_get_features_access(adapter);
92 : :
93 : 0 : access_type = (enum idpf_ptp_access)ptp->get_dev_clk_time_access;
94 [ # # ]: 0 : if (access_type == IDPF_PTP_DIRECT) {
95 : 0 : clock_offsets = recv_ptp_caps_msg->clk_offsets;
96 : :
97 : : temp_offset = LE32_TO_CPU(clock_offsets.dev_clk_ns_l);
98 : 0 : ptp->dev_clk_regs.dev_clk_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
99 : : temp_offset = LE32_TO_CPU(clock_offsets.dev_clk_ns_h);
100 : 0 : ptp->dev_clk_regs.dev_clk_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
101 : : temp_offset = LE32_TO_CPU(clock_offsets.phy_clk_ns_l);
102 : 0 : ptp->dev_clk_regs.phy_clk_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
103 : : temp_offset = LE32_TO_CPU(clock_offsets.phy_clk_ns_h);
104 : 0 : ptp->dev_clk_regs.phy_clk_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
105 : : temp_offset = LE32_TO_CPU(clock_offsets.cmd_sync_trigger);
106 : 0 : ptp->dev_clk_regs.cmd_sync = IDPF_PCI_REG_ADDR(hw, temp_offset);
107 : : }
108 : :
109 : 0 : access_type = (enum idpf_ptp_access)ptp->get_cross_tstamp_access;
110 [ # # ]: 0 : if (access_type == IDPF_PTP_DIRECT) {
111 : 0 : cross_tstamp_offsets = recv_ptp_caps_msg->cross_time_offsets;
112 : :
113 : : temp_offset = LE32_TO_CPU(cross_tstamp_offsets.sys_time_ns_l);
114 : 0 : ptp->dev_clk_regs.sys_time_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
115 : : temp_offset = LE32_TO_CPU(cross_tstamp_offsets.sys_time_ns_h);
116 : 0 : ptp->dev_clk_regs.sys_time_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
117 : : temp_offset = LE32_TO_CPU(cross_tstamp_offsets.cmd_sync_trigger);
118 : 0 : ptp->dev_clk_regs.cmd_sync = IDPF_PCI_REG_ADDR(hw, temp_offset);
119 : : }
120 : :
121 : 0 : access_type = (enum idpf_ptp_access)ptp->adj_dev_clk_time_access;
122 [ # # ]: 0 : if (access_type == IDPF_PTP_DIRECT) {
123 : 0 : clk_adj_offsets = recv_ptp_caps_msg->clk_adj_offsets;
124 : :
125 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_cmd_type);
126 : 0 : ptp->dev_clk_regs.cmd = IDPF_PCI_REG_ADDR(hw, temp_offset);
127 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_incval_l);
128 : 0 : ptp->dev_clk_regs.incval_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
129 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_incval_h);
130 : 0 : ptp->dev_clk_regs.incval_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
131 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_shadj_l);
132 : 0 : ptp->dev_clk_regs.shadj_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
133 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_shadj_h);
134 : 0 : ptp->dev_clk_regs.shadj_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
135 : :
136 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_cmd_type);
137 : 0 : ptp->dev_clk_regs.phy_cmd = IDPF_PCI_REG_ADDR(hw, temp_offset);
138 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_incval_l);
139 : 0 : ptp->dev_clk_regs.phy_incval_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
140 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_incval_h);
141 : 0 : ptp->dev_clk_regs.phy_incval_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
142 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_shadj_l);
143 : 0 : ptp->dev_clk_regs.phy_shadj_l = IDPF_PCI_REG_ADDR(hw, temp_offset);
144 : : temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_shadj_h);
145 : 0 : ptp->dev_clk_regs.phy_shadj_h = IDPF_PCI_REG_ADDR(hw, temp_offset);
146 : : }
147 : :
148 : : return err;
149 : : }
150 : :
151 : : static void
152 : : idpf_ptp_enable_shtime(struct idpf_adapter *adapter)
153 : : {
154 : : uint32_t shtime_enable, exec_cmd;
155 : :
156 : 0 : shtime_enable = adapter->ptp->cmd.shtime_enable_mask;
157 : 0 : exec_cmd = adapter->ptp->cmd.exec_cmd_mask;
158 : :
159 : 0 : IDPF_PCI_REG_WRITE(adapter->ptp->dev_clk_regs.cmd_sync, shtime_enable);
160 : 0 : IDPF_PCI_REG_WRITE(adapter->ptp->dev_clk_regs.cmd_sync,
161 : : exec_cmd | shtime_enable);
162 : : }
163 : :
164 : : int
165 : 0 : idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
166 : : struct idpf_ptp_dev_timers *dev_clk_time)
167 : : {
168 : 0 : struct virtchnl2_ptp_get_dev_clk_time get_dev_clk_time_msg = {0};
169 : 0 : struct idpf_cmd_info args = {0};
170 : : int err;
171 : : uint64_t dev_time;
172 : :
173 : 0 : args.ops = VIRTCHNL2_OP_PTP_GET_DEV_CLK_TIME;
174 : 0 : args.in_args = (uint8_t *)&get_dev_clk_time_msg;
175 : 0 : args.in_args_size = sizeof(get_dev_clk_time_msg);
176 : 0 : args.out_buffer = adapter->mbx_resp;
177 : 0 : args.out_size = sizeof(get_dev_clk_time_msg);
178 : :
179 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
180 [ # # ]: 0 : if (err < 0)
181 : : return err;
182 : :
183 : 0 : get_dev_clk_time_msg =
184 : 0 : *(struct virtchnl2_ptp_get_dev_clk_time *)args.out_buffer;
185 : 0 : dev_time = LE64_TO_CPU(get_dev_clk_time_msg.dev_time_ns);
186 : 0 : dev_clk_time->dev_clk_time_ns = dev_time;
187 : :
188 : 0 : return err;
189 : : }
190 : :
191 : : int
192 : 0 : idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
193 : : struct idpf_ptp_dev_timers *cross_time)
194 : : {
195 : 0 : struct virtchnl2_ptp_get_cross_time cross_time_msg = {0};
196 : 0 : struct idpf_cmd_info args = {0};
197 : : int err;
198 : :
199 : 0 : args.ops = VIRTCHNL2_OP_PTP_GET_CROSS_TIME;
200 : 0 : args.in_args = (uint8_t *)&cross_time_msg;
201 : 0 : args.in_args_size = sizeof(cross_time_msg);
202 : 0 : args.out_buffer = adapter->mbx_resp;
203 : 0 : args.out_size = sizeof(cross_time_msg);
204 : :
205 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
206 [ # # ]: 0 : if (err < 0)
207 : : return err;
208 : :
209 : 0 : cross_time_msg =
210 : 0 : *(struct virtchnl2_ptp_get_cross_time *)args.out_buffer;
211 : 0 : cross_time->dev_clk_time_ns = LE64_TO_CPU(cross_time_msg.dev_time_ns);
212 : 0 : cross_time->sys_time_ns = LE64_TO_CPU(cross_time_msg.sys_time_ns);
213 : :
214 : 0 : return err;
215 : : }
216 : :
217 : : RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_set_dev_clk_time)
218 : : int
219 : 0 : idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, uint64_t time)
220 : : {
221 : 0 : struct virtchnl2_ptp_set_dev_clk_time set_dev_clk_time_msg = {0};
222 : 0 : struct idpf_cmd_info args = {0};
223 : : int err;
224 : :
225 : 0 : set_dev_clk_time_msg.dev_time_ns = CPU_TO_LE64(time);
226 : :
227 : 0 : args.ops = VIRTCHNL2_OP_PTP_SET_DEV_CLK_TIME;
228 : 0 : args.in_args = (uint8_t *)&set_dev_clk_time_msg;
229 : 0 : args.in_args_size = sizeof(set_dev_clk_time_msg);
230 : 0 : args.out_buffer = adapter->mbx_resp;
231 : 0 : args.out_size = sizeof(set_dev_clk_time_msg);
232 : :
233 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
234 : : if (err < 0)
235 : : return err;
236 : :
237 : : return err;
238 : : }
239 : :
240 : : int
241 : 0 : idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, int64_t delta)
242 : : {
243 : : struct virtchnl2_ptp_adj_dev_clk_time adj_dev_clk_time_msg = {0};
244 : 0 : struct idpf_cmd_info args = {0};
245 : : int err;
246 : :
247 : 0 : adj_dev_clk_time_msg.delta = CPU_TO_LE64(delta);
248 : :
249 : 0 : args.ops = VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_TIME;
250 : 0 : args.in_args = (uint8_t *)&adj_dev_clk_time_msg;
251 : 0 : args.in_args_size = sizeof(adj_dev_clk_time_msg);
252 : 0 : args.out_buffer = adapter->mbx_resp;
253 : 0 : args.out_size = sizeof(adj_dev_clk_time_msg);
254 : :
255 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
256 : : if (err < 0)
257 : : return err;
258 : :
259 : : return err;
260 : : }
261 : :
262 : : RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_adj_dev_clk_fine)
263 : : int
264 : 0 : idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, uint64_t incval)
265 : : {
266 : : struct virtchnl2_ptp_adj_dev_clk_fine adj_dev_clk_fine_msg = {0};
267 : 0 : struct idpf_cmd_info args = {0};
268 : : int err;
269 : :
270 : 0 : adj_dev_clk_fine_msg.incval = CPU_TO_LE64(incval);
271 : :
272 : 0 : args.ops = VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_FINE;
273 : 0 : args.in_args = (uint8_t *)&adj_dev_clk_fine_msg;
274 : 0 : args.in_args_size = sizeof(adj_dev_clk_fine_msg);
275 : 0 : args.out_buffer = adapter->mbx_resp;
276 : 0 : args.out_size = sizeof(adj_dev_clk_fine_msg);
277 : :
278 : 0 : err = idpf_vc_cmd_execute(adapter, &args);
279 : : if (err < 0)
280 : : return err;
281 : :
282 : : return err;
283 : : }
284 : :
285 : : int
286 : 0 : idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
287 : : {
288 : 0 : struct virtchnl2_ptp_get_vport_tx_tstamp_caps send_tx_tstamp_caps = {0};
289 : : struct virtchnl2_ptp_get_vport_tx_tstamp_caps *rcv_tx_tstamp_caps;
290 : : struct virtchnl2_ptp_tx_tstamp_latch_caps tx_tstamp_latch_caps;
291 : : enum idpf_ptp_access tstamp_access, get_dev_clk_access;
292 : : struct idpf_ptp_vport_tx_tstamp_caps *tstamp_caps;
293 : 0 : struct idpf_ptp *ptp = vport->adapter->ptp;
294 : 0 : struct idpf_cmd_info args = {0};
295 : : int err;
296 : : uint16_t num_latches, id;
297 : : uint32_t size;
298 : :
299 [ # # ]: 0 : if (ptp == NULL)
300 : : return -EOPNOTSUPP;
301 : :
302 : 0 : tstamp_access = (enum idpf_ptp_access)ptp->tx_tstamp_access;
303 : 0 : get_dev_clk_access = (enum idpf_ptp_access)ptp->get_dev_clk_time_access;
304 : 0 : if (tstamp_access == IDPF_PTP_NONE ||
305 [ # # ]: 0 : get_dev_clk_access == IDPF_PTP_NONE)
306 : : return -EOPNOTSUPP;
307 : :
308 : 0 : send_tx_tstamp_caps.vport_id = CPU_TO_LE32(vport->vport_id);
309 : :
310 : 0 : args.ops = VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP_CAPS;
311 : 0 : args.in_args = (uint8_t *)&send_tx_tstamp_caps;
312 : 0 : args.in_args_size = sizeof(send_tx_tstamp_caps);
313 : 0 : args.out_size = IDPF_CTLQ_MAX_BUF_LEN;
314 : 0 : args.out_buffer = vport->adapter->mbx_resp;
315 : :
316 : 0 : err = idpf_vc_cmd_execute(vport->adapter, &args);
317 [ # # ]: 0 : if (err < 0)
318 : : return err;
319 : :
320 : 0 : rcv_tx_tstamp_caps =
321 : : (struct virtchnl2_ptp_get_vport_tx_tstamp_caps *)args.out_buffer;
322 : 0 : num_latches = LE16_TO_CPU(rcv_tx_tstamp_caps->num_latches);
323 : 0 : size = sizeof(struct idpf_ptp_vport_tx_tstamp_caps) +
324 : 0 : sizeof(struct idpf_ptp_tx_tstamp) * num_latches;
325 : 0 : tstamp_caps = rte_zmalloc(NULL, size, 0);
326 [ # # ]: 0 : if (tstamp_caps == NULL)
327 : : return -ENOMEM;
328 : :
329 : 0 : tstamp_caps->access = true;
330 : 0 : tstamp_caps->num_entries = num_latches;
331 : 0 : tstamp_caps->tstamp_ns_lo_bit = rcv_tx_tstamp_caps->tstamp_ns_lo_bit;
332 : :
333 [ # # ]: 0 : for (id = 0; id < tstamp_caps->num_entries; id++) {
334 : : __le32 offset_l, offset_h;
335 : :
336 : 0 : tx_tstamp_latch_caps = rcv_tx_tstamp_caps->tstamp_latches[id];
337 : :
338 [ # # ]: 0 : if (tstamp_access == IDPF_PTP_DIRECT) {
339 : : offset_l = tx_tstamp_latch_caps.tx_latch_reg_offset_l;
340 : : offset_h = tx_tstamp_latch_caps.tx_latch_reg_offset_h;
341 : 0 : tstamp_caps->tx_tstamp[id].tx_latch_reg_offset_l =
342 : : LE32_TO_CPU(offset_l);
343 : 0 : tstamp_caps->tx_tstamp[id].tx_latch_reg_offset_h =
344 : : LE32_TO_CPU(offset_h);
345 : : }
346 : 0 : tstamp_caps->tx_tstamp[id].idx = tx_tstamp_latch_caps.index;
347 : : }
348 : :
349 : 0 : tstamp_caps->latched_idx = -1;
350 : 0 : vport->tx_tstamp_caps = tstamp_caps;
351 : :
352 : 0 : return err;
353 : : }
354 : :
355 : : static int
356 : : idpf_ptp_get_tstamp_value(struct idpf_vport *vport,
357 : : struct virtchnl2_ptp_tx_tstamp_latch *tstamp_latch,
358 : : struct idpf_ptp_tx_tstamp *tx_tstamp)
359 : : {
360 : : struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
361 : : uint8_t tstamp_ns_lo_bit;
362 : :
363 : 0 : tx_tstamp_caps = vport->tx_tstamp_caps;
364 : 0 : tstamp_ns_lo_bit = tx_tstamp_caps->tstamp_ns_lo_bit;
365 : :
366 : : tx_tstamp->tstamp = LE64_TO_CPU(tstamp_latch->tstamp);
367 : 0 : tx_tstamp->tstamp >>= tstamp_ns_lo_bit;
368 : :
369 : : return 0;
370 : : }
371 : :
372 : : int
373 : 0 : idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
374 : : {
375 : : struct virtchnl2_ptp_get_vport_tx_tstamp_latches *send_tx_tstamp_msg;
376 : : struct virtchnl2_ptp_get_vport_tx_tstamp_latches *recv_tx_tstamp_msg;
377 : : struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;
378 : : struct virtchnl2_ptp_tx_tstamp_latch tstamp_latch;
379 : : struct idpf_ptp_tx_tstamp *ptp_tx_tstamp;
380 : 0 : struct idpf_cmd_info args = {0};
381 : : int size, msg_size;
382 : : uint32_t vport_id;
383 : : uint16_t num_latches, id;
384 : : int err;
385 : :
386 : 0 : tx_tstamp_caps = vport->tx_tstamp_caps;
387 : 0 : ptp_tx_tstamp = tx_tstamp_caps->tx_tstamp;
388 : :
389 : 0 : size = sizeof(struct virtchnl2_ptp_get_vport_tx_tstamp_latches) +
390 : : sizeof(struct virtchnl2_ptp_tx_tstamp_latch) *
391 : 0 : tx_tstamp_caps->num_entries;
392 : 0 : send_tx_tstamp_msg = rte_zmalloc(NULL, size, 0);
393 [ # # ]: 0 : if (send_tx_tstamp_msg == NULL)
394 : : return -ENOMEM;
395 : :
396 [ # # ]: 0 : for (id = 0; id < tx_tstamp_caps->num_entries; id++, ptp_tx_tstamp++)
397 : 0 : send_tx_tstamp_msg->tstamp_latches[id].index = ptp_tx_tstamp->idx;
398 : 0 : send_tx_tstamp_msg->get_devtime_with_txtstmp = 1;
399 : :
400 : 0 : msg_size = sizeof(struct virtchnl2_ptp_get_vport_tx_tstamp_latches) +
401 : : sizeof(struct virtchnl2_ptp_tx_tstamp_latch) * id;
402 : 0 : send_tx_tstamp_msg->vport_id = CPU_TO_LE32(vport->vport_id);
403 : 0 : send_tx_tstamp_msg->num_latches = CPU_TO_LE16(id);
404 : :
405 : 0 : args.ops = VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP;
406 : 0 : args.in_args = (uint8_t *)send_tx_tstamp_msg;
407 : 0 : args.in_args_size = msg_size;
408 : 0 : args.out_size = msg_size;
409 : 0 : args.out_buffer = vport->adapter->mbx_resp;
410 : :
411 : 0 : err = idpf_vc_cmd_execute(vport->adapter, &args);
412 : 0 : rte_free(send_tx_tstamp_msg);
413 [ # # ]: 0 : if (err < 0)
414 : : return err;
415 : :
416 : 0 : recv_tx_tstamp_msg =
417 : : (struct virtchnl2_ptp_get_vport_tx_tstamp_latches *)args.out_buffer;
418 : 0 : vport_id = LE32_TO_CPU(recv_tx_tstamp_msg->vport_id);
419 [ # # ]: 0 : if (vport->vport_id != vport_id)
420 : : return -EINVAL;
421 : :
422 : 0 : num_latches = LE16_TO_CPU(recv_tx_tstamp_msg->num_latches);
423 : :
424 : : ptp_tx_tstamp = tx_tstamp_caps->tx_tstamp;
425 [ # # ]: 0 : for (id = 0; id < num_latches; id++, ptp_tx_tstamp++) {
426 : 0 : tstamp_latch = recv_tx_tstamp_msg->tstamp_latches[id];
427 : :
428 [ # # ]: 0 : if (!tstamp_latch.valid)
429 : : continue;
430 : :
431 : : err = idpf_ptp_get_tstamp_value(vport, &tstamp_latch,
432 : : ptp_tx_tstamp);
433 : : if (err == 0) {
434 : 0 : tx_tstamp_caps->latched_idx = id;
435 : 0 : vport->adapter->time_hw = recv_tx_tstamp_msg->device_time;
436 : : }
437 : : break;
438 : : }
439 : :
440 : : return err;
441 : : }
442 : :
443 : : /**
444 : : * idpf_ptp_read_src_clk_reg_direct - Read directly the main timer value
445 : : * @adapter: Driver specific private structure
446 : : * @src_clk: Returned main timer value in nanoseconds unit
447 : : *
448 : : * Return: 0 on success, -errno otherwise.
449 : : */
450 : : static int
451 : 0 : idpf_ptp_read_src_clk_reg_direct(struct idpf_adapter *adapter, uint64_t *src_clk)
452 : : {
453 : 0 : struct idpf_ptp *ptp = adapter->ptp;
454 : : uint32_t hi, lo;
455 : :
456 : : idpf_ptp_enable_shtime(adapter);
457 : :
458 : 0 : lo = IDPF_PCI_REG(ptp->dev_clk_regs.dev_clk_ns_l);
459 : 0 : hi = IDPF_PCI_REG(ptp->dev_clk_regs.dev_clk_ns_h);
460 : :
461 : 0 : *src_clk = ((uint64_t)hi << 32) | lo;
462 : 0 : return 0;
463 : : }
464 : :
465 : : /**
466 : : * idpf_ptp_read_src_clk_reg_mailbox - Read the main timer value through mailbox
467 : : * @adapter: Driver specific private structure
468 : : * @src_clk: Returned main timer value in nanoseconds unit
469 : : *
470 : : * Return: 0 on success, -errno otherwise.
471 : : */
472 : : static int
473 : : idpf_ptp_read_src_clk_reg_mailbox(struct idpf_adapter *adapter,
474 : : uint64_t *src_clk)
475 : : {
476 : : struct idpf_ptp_dev_timers clk_time;
477 : : int err;
478 : :
479 : 0 : err = idpf_ptp_get_dev_clk_time(adapter, &clk_time);
480 [ # # ]: 0 : if (err)
481 : : return err;
482 : :
483 : 0 : *src_clk = clk_time.dev_clk_time_ns;
484 : 0 : return 0;
485 : : }
486 : :
487 : : /**
488 : : * idpf_ptp_read_src_clk_reg - Read the main timer value
489 : : * @adapter: Driver specific private structure
490 : : * @src_clk: Returned main timer value in nanoseconds unit
491 : : *
492 : : * Return: 0 on success, -errno otherwise.
493 : : */
494 : : RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_read_src_clk_reg)
495 : : int
496 : 0 : idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, uint64_t *src_clk)
497 : : {
498 [ # # ]: 0 : if (adapter->ptp == NULL)
499 : : return -EINVAL;
500 : :
501 [ # # # ]: 0 : switch ((enum idpf_ptp_access)adapter->ptp->get_dev_clk_time_access) {
502 : : case IDPF_PTP_MAILBOX:
503 : 0 : return idpf_ptp_read_src_clk_reg_mailbox(adapter, src_clk);
504 : 0 : case IDPF_PTP_DIRECT:
505 : 0 : return idpf_ptp_read_src_clk_reg_direct(adapter, src_clk);
506 : : default:
507 : : return -EOPNOTSUPP;
508 : : }
509 : : }
|