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