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