net/memif: fix overwriting of head segment
[dpdk.git] / drivers / net / hns3 / hns3_ptp.c
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_regs.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 hns3_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 & RTE_ETH_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
39 static int
40 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         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
59 int
60 hns3_ptp_init(struct hns3_hw *hw)
61 {
62         int ret;
63
64         if (!hns3_dev_get_support(hw, PTP))
65                 return 0;
66
67         ret = hns3_ptp_int_en(hw, true);
68         if (ret)
69                 return ret;
70
71         /* Start PTP timer */
72         hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1);
73
74         return 0;
75 }
76
77 static int
78 hns3_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
115 int
116 hns3_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_get_support(hw, PTP))
124                 return -ENOTSUP;
125
126         if (pf->ptp_enable)
127                 return 0;
128         hns3_warn(hw, "note: please ensure Rx/Tx burst mode is simple or common when enabling PTP!");
129
130         rte_spinlock_lock(&hw->lock);
131         ret = hns3_timesync_configure(hns, true);
132         rte_spinlock_unlock(&hw->lock);
133         return ret;
134 }
135
136 int
137 hns3_timesync_disable(struct rte_eth_dev *dev)
138 {
139         struct hns3_adapter *hns = dev->data->dev_private;
140         struct hns3_hw *hw = &hns->hw;
141         struct hns3_pf *pf = &hns->pf;
142         int ret;
143
144         if (!hns3_dev_get_support(hw, PTP))
145                 return -ENOTSUP;
146
147         if (!pf->ptp_enable)
148                 return 0;
149
150         rte_spinlock_lock(&hw->lock);
151         ret = hns3_timesync_configure(hns, false);
152         rte_spinlock_unlock(&hw->lock);
153
154         return ret;
155 }
156
157 int
158 hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
159                                 struct timespec *timestamp,
160                                 uint32_t flags __rte_unused)
161 {
162 #define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF
163         struct hns3_adapter *hns = dev->data->dev_private;
164         struct hns3_hw *hw = &hns->hw;
165         struct hns3_pf *pf = &hns->pf;
166         uint64_t ns, sec;
167
168         if (!hns3_dev_get_support(hw, PTP))
169                 return -ENOTSUP;
170
171         ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK;
172         sec = upper_32_bits(pf->rx_timestamp);
173
174         ns += sec * NSEC_PER_SEC;
175         *timestamp = rte_ns_to_timespec(ns);
176
177         return 0;
178 }
179
180 int
181 hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
182                                 struct timespec *timestamp)
183 {
184 #define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF
185 #define TIME_TX_STAMP_VALID   24
186 #define TIME_TX_STAMP_CNT_MASK 0x7
187         struct hns3_adapter *hns = dev->data->dev_private;
188         struct hns3_hw *hw = &hns->hw;
189         uint64_t sec;
190         uint64_t tmp;
191         uint64_t ns;
192         int ts_cnt;
193
194         if (!hns3_dev_get_support(hw, PTP))
195                 return -ENOTSUP;
196
197         ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) &
198                         TIME_TX_STAMP_CNT_MASK;
199         if (ts_cnt == 0)
200                 return -EINVAL;
201
202         ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK;
203         sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1);
204         tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF;
205         sec = (tmp << 32) | sec;
206
207         ns += sec * NSEC_PER_SEC;
208
209         *timestamp = rte_ns_to_timespec(ns);
210
211         /* Clear current timestamp hardware stores */
212         hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK);
213
214         return 0;
215 }
216
217 int
218 hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
219 {
220         struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
221         uint64_t ns, sec;
222
223         if (!hns3_dev_get_support(hw, PTP))
224                 return -ENOTSUP;
225
226         sec = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L);
227         sec |= (uint64_t)(hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & 0xFFFF)
228                 << 32;
229
230         ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS);
231         ns += sec * NSEC_PER_SEC;
232         *ts = rte_ns_to_timespec(ns);
233
234         return 0;
235 }
236
237 int
238 hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
239 {
240         struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
241         uint64_t sec = ts->tv_sec;
242         uint64_t ns = ts->tv_nsec;
243
244         if (!hns3_dev_get_support(hw, PTP))
245                 return -ENOTSUP;
246
247         /* Set the timecounters to a new value. */
248         hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec));
249         hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec));
250         hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns));
251         hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1);
252
253         return 0;
254 }
255
256 int
257 hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
258 {
259 #define TIME_SYNC_L_MASK 0x7FFFFFFF
260 #define SYMBOL_BIT_OFFSET 31
261         struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
262         struct timespec cur_time;
263         uint64_t ns;
264
265         if (!hns3_dev_get_support(hw, PTP))
266                 return -ENOTSUP;
267
268         (void)hns3_timesync_read_time(dev, &cur_time);
269         ns = rte_timespec_to_ns((const struct timespec *)&cur_time);
270         cur_time = rte_ns_to_timespec(ns + delta);
271         (void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time);
272
273         return 0;
274 }
275
276 int
277 hns3_restore_ptp(struct hns3_adapter *hns)
278 {
279         struct hns3_pf *pf = &hns->pf;
280         struct hns3_hw *hw = &hns->hw;
281         bool en = pf->ptp_enable;
282         int ret;
283
284         if (!hns3_dev_get_support(hw, PTP))
285                 return 0;
286
287         ret = hns3_timesync_configure(hns, en);
288         if (ret)
289                 hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d",
290                          en, ret);
291
292         return ret;
293 }