Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2021-2021 Hisilicon Limited.
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : : #include <rte_io.h>
7 : : #include <rte_time.h>
8 : :
9 : : #include "hns3_ethdev.h"
10 : : #include "hns3_ptp.h"
11 : : #include "hns3_logs.h"
12 : :
13 : : uint64_t hns3_timestamp_rx_dynflag;
14 : : int hns3_timestamp_dynfield_offset = -1;
15 : :
16 : : int
17 : 0 : hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
18 : : struct rte_eth_conf *conf)
19 : : {
20 : 0 : struct hns3_adapter *hns = dev->data->dev_private;
21 : : struct hns3_hw *hw = &hns->hw;
22 : : int ret;
23 : :
24 [ # # ]: 0 : if (!(conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP))
25 : : return 0;
26 : :
27 : 0 : ret = rte_mbuf_dyn_rx_timestamp_register
28 : : (&hns3_timestamp_dynfield_offset,
29 : : &hns3_timestamp_rx_dynflag);
30 [ # # ]: 0 : if (ret) {
31 : 0 : hns3_err(hw,
32 : : "failed to register Rx timestamp field/flag");
33 : 0 : return ret;
34 : : }
35 : :
36 : : return 0;
37 : : }
38 : :
39 : : static int
40 : 0 : hns3_ptp_int_en(struct hns3_hw *hw, bool en)
41 : : {
42 : : struct hns3_ptp_int_cmd *req;
43 : : struct hns3_cmd_desc desc;
44 : : int ret;
45 : :
46 : : req = (struct hns3_ptp_int_cmd *)desc.data;
47 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false);
48 : 0 : req->int_en = en ? 1 : 0;
49 : :
50 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
51 [ # # ]: 0 : if (ret)
52 [ # # ]: 0 : hns3_err(hw,
53 : : "failed to %s ptp interrupt, ret = %d",
54 : : en ? "enable" : "disable", ret);
55 : :
56 : 0 : return ret;
57 : : }
58 : :
59 : : static void
60 : : hns3_ptp_timesync_write_time(struct hns3_hw *hw, const struct timespec *ts)
61 : : {
62 : 0 : uint64_t sec = ts->tv_sec;
63 : 0 : uint64_t ns = ts->tv_nsec;
64 : :
65 : : /* Set the timecounters to a new value. */
66 : 0 : hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec));
67 : 0 : hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec));
68 : 0 : hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns));
69 : 0 : hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1);
70 : : }
71 : :
72 : : int
73 : 0 : hns3_ptp_init(struct hns3_hw *hw)
74 : : {
75 : : struct timespec sys_time;
76 : : int ret;
77 : :
78 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
79 : : return 0;
80 : :
81 : 0 : ret = hns3_ptp_int_en(hw, true);
82 [ # # ]: 0 : if (ret)
83 : : return ret;
84 : :
85 : : /* Start PTP timer */
86 : 0 : hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1);
87 : :
88 : : /* Initializing the RTC. */
89 : 0 : clock_gettime(CLOCK_REALTIME, &sys_time);
90 : : hns3_ptp_timesync_write_time(hw, &sys_time);
91 : :
92 : 0 : return 0;
93 : : }
94 : :
95 : : static int
96 : 0 : hns3_timesync_configure(struct hns3_adapter *hns, bool en)
97 : : {
98 : : struct hns3_ptp_mode_cfg_cmd *req;
99 : 0 : struct hns3_hw *hw = &hns->hw;
100 : : struct hns3_pf *pf = &hns->pf;
101 : : struct hns3_cmd_desc desc;
102 : : uint32_t val;
103 : : int ret;
104 : :
105 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false);
106 : :
107 : : req = (struct hns3_ptp_mode_cfg_cmd *)desc.data;
108 : :
109 : : val = en ? 1 : 0;
110 : 0 : hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val);
111 : 0 : hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val);
112 : 0 : hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val);
113 : :
114 [ # # ]: 0 : if (en) {
115 : 0 : hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S,
116 : : PTP_TYPE_L2_V2_TYPE);
117 : 0 : hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M,
118 : : HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE);
119 : : }
120 : :
121 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
122 [ # # ]: 0 : if (ret) {
123 : 0 : hns3_err(hw, "configure PTP time failed, en = %d, ret = %d",
124 : : en, ret);
125 : 0 : return ret;
126 : : }
127 : :
128 : 0 : pf->ptp_enable = en;
129 : :
130 : 0 : return 0;
131 : : }
132 : :
133 : : int
134 : 0 : hns3_timesync_enable(struct rte_eth_dev *dev)
135 : : {
136 : 0 : struct hns3_adapter *hns = dev->data->dev_private;
137 : : struct hns3_hw *hw = &hns->hw;
138 : : struct hns3_pf *pf = &hns->pf;
139 : : int ret;
140 : :
141 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
142 : : return -ENOTSUP;
143 : :
144 [ # # ]: 0 : if (pf->ptp_enable)
145 : : return 0;
146 : :
147 : 0 : rte_spinlock_lock(&hw->lock);
148 : 0 : ret = hns3_timesync_configure(hns, true);
149 : : rte_spinlock_unlock(&hw->lock);
150 : 0 : return ret;
151 : : }
152 : :
153 : : int
154 : 0 : hns3_timesync_disable(struct rte_eth_dev *dev)
155 : : {
156 : 0 : struct hns3_adapter *hns = dev->data->dev_private;
157 : : struct hns3_hw *hw = &hns->hw;
158 : : struct hns3_pf *pf = &hns->pf;
159 : : int ret;
160 : :
161 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
162 : : return -ENOTSUP;
163 : :
164 [ # # ]: 0 : if (!pf->ptp_enable)
165 : : return 0;
166 : :
167 : 0 : rte_spinlock_lock(&hw->lock);
168 : 0 : ret = hns3_timesync_configure(hns, false);
169 : : rte_spinlock_unlock(&hw->lock);
170 : :
171 : 0 : return ret;
172 : : }
173 : :
174 : : int
175 : 0 : hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
176 : : struct timespec *timestamp,
177 : : uint32_t flags __rte_unused)
178 : : {
179 : : #define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF
180 : 0 : struct hns3_adapter *hns = dev->data->dev_private;
181 : : struct hns3_hw *hw = &hns->hw;
182 : : struct hns3_pf *pf = &hns->pf;
183 : : uint64_t ns, sec;
184 : :
185 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
186 : : return -ENOTSUP;
187 : :
188 : 0 : ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK;
189 : 0 : sec = upper_32_bits(pf->rx_timestamp);
190 : :
191 [ # # ]: 0 : ns += sec * NSEC_PER_SEC;
192 : 0 : *timestamp = rte_ns_to_timespec(ns);
193 : :
194 : 0 : return 0;
195 : : }
196 : :
197 : : int
198 : 0 : hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
199 : : struct timespec *timestamp)
200 : : {
201 : : #define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF
202 : : #define TIME_TX_STAMP_VALID 24
203 : : #define TIME_TX_STAMP_CNT_MASK 0x7
204 : 0 : struct hns3_adapter *hns = dev->data->dev_private;
205 : : struct hns3_hw *hw = &hns->hw;
206 : : uint64_t sec;
207 : : uint64_t tmp;
208 : : uint64_t ns;
209 : : int ts_cnt;
210 : :
211 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
212 : : return -ENOTSUP;
213 : :
214 : 0 : ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) &
215 : : TIME_TX_STAMP_CNT_MASK;
216 [ # # ]: 0 : if (ts_cnt == 0)
217 : : return -EINVAL;
218 : :
219 : 0 : ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK;
220 : 0 : sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1);
221 : 0 : tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF;
222 : 0 : sec = (tmp << 32) | sec;
223 : :
224 [ # # ]: 0 : ns += sec * NSEC_PER_SEC;
225 : :
226 : 0 : *timestamp = rte_ns_to_timespec(ns);
227 : :
228 : : /* Clear current timestamp hardware stores */
229 : 0 : hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK);
230 : :
231 : 0 : return 0;
232 : : }
233 : :
234 : : int
235 : 0 : hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
236 : : {
237 : : #define HNS3_PTP_SEC_H_OFFSET 32
238 : : #define HNS3_PTP_SEC_H_MASK 0xFFFF
239 : :
240 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
241 : : uint32_t sec_hi, sec_lo;
242 : : uint64_t ns, sec;
243 : :
244 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
245 : : return -ENOTSUP;
246 : :
247 : 0 : ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS);
248 : 0 : sec_hi = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & HNS3_PTP_SEC_H_MASK;
249 : 0 : sec_lo = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L);
250 : 0 : sec = ((uint64_t)sec_hi << HNS3_PTP_SEC_H_OFFSET) | sec_lo;
251 : :
252 [ # # ]: 0 : ns += sec * NSEC_PER_SEC;
253 : 0 : *ts = rte_ns_to_timespec(ns);
254 : :
255 : 0 : return 0;
256 : : }
257 : :
258 : : int
259 : 0 : hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
260 : : {
261 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
262 : :
263 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
264 : : return -ENOTSUP;
265 : :
266 : : hns3_ptp_timesync_write_time(hw, ts);
267 : :
268 : 0 : return 0;
269 : : }
270 : :
271 : : int
272 : 0 : hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
273 : : {
274 : : #define TIME_SYNC_L_MASK 0x7FFFFFFF
275 : : #define SYMBOL_BIT_OFFSET 31
276 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
277 : : struct timespec cur_time;
278 : : uint64_t ns;
279 : :
280 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
281 : : return -ENOTSUP;
282 : :
283 : 0 : (void)hns3_timesync_read_time(dev, &cur_time);
284 : : ns = rte_timespec_to_ns((const struct timespec *)&cur_time);
285 [ # # ]: 0 : cur_time = rte_ns_to_timespec(ns + delta);
286 : 0 : (void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time);
287 : :
288 : 0 : return 0;
289 : : }
290 : :
291 : : int
292 : 0 : hns3_restore_ptp(struct hns3_adapter *hns)
293 : : {
294 : : struct hns3_pf *pf = &hns->pf;
295 : : struct hns3_hw *hw = &hns->hw;
296 : 0 : bool en = pf->ptp_enable;
297 : : int ret;
298 : :
299 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
300 : : return 0;
301 : :
302 : 0 : ret = hns3_timesync_configure(hns, en);
303 [ # # ]: 0 : if (ret)
304 : 0 : hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d",
305 : : en, ret);
306 : :
307 : : return ret;
308 : : }
309 : :
310 : : void
311 : 0 : hns3_ptp_uninit(struct hns3_hw *hw)
312 : : {
313 : : struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
314 : : int ret;
315 : :
316 [ # # ]: 0 : if (!hns3_dev_get_support(hw, PTP))
317 : : return;
318 : :
319 : 0 : ret = hns3_ptp_int_en(hw, false);
320 [ # # ]: 0 : if (ret != 0)
321 : 0 : hns3_err(hw, "disable PTP interrupt failed, ret = %d.", ret);
322 : :
323 : 0 : ret = hns3_timesync_configure(hns, false);
324 [ # # ]: 0 : if (ret != 0)
325 : 0 : hns3_err(hw, "disable timesync failed, ret = %d.", ret);
326 : : }
|