1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
3 */
4 #include <stdio.h>
5
6 #include <rte_errno.h>
7 #include <rte_ether.h>
8 #include <ethdev_driver.h>
9 #include <rte_interrupts.h>
10
11 #include <mlx5_glue.h>
12 #include <mlx5_devx_cmds.h>
13 #include <mlx5_common.h>
14 #include <mlx5_win_ext.h>
15 #include <mlx5_malloc.h>
16 #include <mlx5.h>
17 #include <mlx5_utils.h>
18
19 /**
20 * Get MAC address by querying netdevice.
21 *
22 * @param[in] dev
23 * Pointer to Ethernet device.
24 * @param[out] mac
25 * MAC address output buffer.
26 *
27 * @return
28 * 0 on success, a negative errno value otherwise and rte_errno is set.
29 */
30 int
mlx5_get_mac(struct rte_eth_dev * dev,uint8_t (* mac)[RTE_ETHER_ADDR_LEN])31 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN])
32 {
33 struct mlx5_priv *priv;
34 mlx5_context_st *context_obj;
35
36 if (!dev) {
37 rte_errno = EINVAL;
38 return -rte_errno;
39 }
40 priv = dev->data->dev_private;
41 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
42 memcpy(mac, context_obj->mlx5_dev.eth_mac, RTE_ETHER_ADDR_LEN);
43 return 0;
44 }
45
46 /**
47 * Get interface name from private structure.
48 *
49 *
50 * @param[in] dev
51 * Pointer to Ethernet device.
52 * @param[out] ifname
53 * Interface name output buffer.
54 *
55 * @return
56 * 0 on success, a negative errno value otherwise and rte_errno is set.
57 */
58 int
mlx5_get_ifname(const struct rte_eth_dev * dev,char (* ifname)[MLX5_NAMESIZE])59 mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[MLX5_NAMESIZE])
60 {
61 struct mlx5_priv *priv;
62 mlx5_context_st *context_obj;
63
64 if (!dev) {
65 rte_errno = EINVAL;
66 return -rte_errno;
67 }
68 priv = dev->data->dev_private;
69 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
70 strncpy(*ifname, context_obj->mlx5_dev.name, MLX5_NAMESIZE);
71 return 0;
72 }
73
74 /**
75 * Get device MTU.
76 *
77 * @param dev
78 * Pointer to Ethernet device.
79 * @param[out] mtu
80 * MTU value output buffer.
81 *
82 * @return
83 * 0 on success, a negative errno value otherwise and rte_errno is set.
84 */
85 int
mlx5_get_mtu(struct rte_eth_dev * dev,uint16_t * mtu)86 mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
87 {
88 int err;
89 uint32_t curr_mtu;
90 struct mlx5_priv *priv;
91 mlx5_context_st *context_obj;
92
93 if (!dev) {
94 rte_errno = EINVAL;
95 return -rte_errno;
96 }
97 priv = dev->data->dev_private;
98 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
99
100 err = mlx5_glue->devx_get_mtu(context_obj, &curr_mtu);
101 if (err != 0) {
102 DRV_LOG(WARNING, "Could not get the MTU!");
103 return err;
104 }
105 *mtu = (uint16_t)curr_mtu;
106
107 return 0;
108 }
109
110 /**
111 * Set device MTU.
112 *
113 * @param dev
114 * Pointer to Ethernet device.
115 * @param mtu
116 * MTU value to set.
117 *
118 * @return
119 * 0 on success, a negative errno value otherwise and rte_errno is set.
120 */
121 int
mlx5_set_mtu(struct rte_eth_dev * dev,uint16_t mtu)122 mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
123 {
124 int err;
125 struct mlx5_priv *priv;
126 mlx5_context_st *context_obj;
127
128 if (!dev) {
129 rte_errno = EINVAL;
130 return -rte_errno;
131 }
132 priv = dev->data->dev_private;
133 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
134
135 err = mlx5_glue->devx_set_mtu(context_obj, mtu);
136 if (err != 0) {
137 DRV_LOG(WARNING, "Could not set the MTU!");
138 return err;
139 }
140 return 0;
141 }
142
143 /*
144 * Unregister callback handler safely. The handler may be active
145 * while we are trying to unregister it, in this case code -EAGAIN
146 * is returned by rte_intr_callback_unregister(). This routine checks
147 * the return code and tries to unregister handler again.
148 *
149 * @param handle
150 * interrupt handle
151 * @param cb_fn
152 * pointer to callback routine
153 * @cb_arg
154 * opaque callback parameter
155 */
156 void
mlx5_intr_callback_unregister(const struct rte_intr_handle * handle,rte_intr_callback_fn cb_fn,void * cb_arg)157 mlx5_intr_callback_unregister(const struct rte_intr_handle *handle,
158 rte_intr_callback_fn cb_fn, void *cb_arg)
159 {
160 RTE_SET_USED(handle);
161 RTE_SET_USED(cb_fn);
162 RTE_SET_USED(cb_arg);
163 }
164
165 /**
166 * DPDK callback to get flow control status.
167 *
168 * @param dev
169 * Pointer to Ethernet device structure.
170 * @param[out] fc_conf
171 * Flow control output buffer.
172 *
173 * @return
174 * 0 on success, a negative errno value otherwise and rte_errno is set.
175 */
176 int
mlx5_dev_get_flow_ctrl(struct rte_eth_dev * dev,struct rte_eth_fc_conf * fc_conf)177 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
178 {
179 RTE_SET_USED(dev);
180 RTE_SET_USED(fc_conf);
181 return -ENOTSUP;
182 }
183
184 /**
185 * DPDK callback to modify flow control parameters.
186 *
187 * @param dev
188 * Pointer to Ethernet device structure.
189 * @param[in] fc_conf
190 * Flow control parameters.
191 *
192 * @return
193 * 0 on success, a negative errno value otherwise and rte_errno is set.
194 */
195 int
mlx5_dev_set_flow_ctrl(struct rte_eth_dev * dev,struct rte_eth_fc_conf * fc_conf)196 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
197 {
198 RTE_SET_USED(dev);
199 RTE_SET_USED(fc_conf);
200 return -ENOTSUP;
201 }
202
203 /**
204 * Query the number of statistics provided by ETHTOOL.
205 *
206 * @param dev
207 * Pointer to Ethernet device.
208 *
209 * @return
210 * Number of statistics on success, negative errno value otherwise and
211 * rte_errno is set.
212 */
213 int
mlx5_os_get_stats_n(struct rte_eth_dev * dev)214 mlx5_os_get_stats_n(struct rte_eth_dev *dev)
215 {
216 RTE_SET_USED(dev);
217 return -ENOTSUP;
218 }
219
220 /**
221 * Init the structures to read device counters.
222 *
223 * @param dev
224 * Pointer to Ethernet device.
225 */
226 void
mlx5_os_stats_init(struct rte_eth_dev * dev)227 mlx5_os_stats_init(struct rte_eth_dev *dev)
228 {
229 struct mlx5_priv *priv = dev->data->dev_private;
230 struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
231 int ret;
232
233 /* Copy to base at first time. */
234 ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
235 if (ret)
236 DRV_LOG(ERR, "port %u cannot read device counters: %s",
237 dev->data->port_id, strerror(rte_errno));
238 stats_ctrl->imissed = 0;
239 }
240
241 /**
242 * Read device counters table.
243 *
244 * @param dev
245 * Pointer to Ethernet device.
246 * @param[out] stats
247 * Counters table output buffer.
248 *
249 * @return
250 * 0 on success and stats is filled, negative errno value otherwise and
251 * rte_errno is set.
252 */
253 int
mlx5_os_read_dev_counters(struct rte_eth_dev * dev,uint64_t * stats)254 mlx5_os_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
255 {
256 RTE_SET_USED(dev);
257 RTE_SET_USED(stats);
258 return -ENOTSUP;
259 }
260
261 /**
262 * DPDK callback to retrieve physical link information.
263 *
264 * @param dev
265 * Pointer to Ethernet device structure.
266 * @param wait_to_complete
267 * Wait for request completion.
268 *
269 * @return
270 * 0 if link status was not updated, positive if it was, a negative errno
271 * value otherwise and rte_errno is set.
272 */
273 int
mlx5_link_update(struct rte_eth_dev * dev,int wait_to_complete)274 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete)
275 {
276 RTE_SET_USED(wait_to_complete);
277 struct mlx5_priv *priv;
278 mlx5_context_st *context_obj;
279 struct rte_eth_link dev_link;
280 int ret;
281
282 ret = 0;
283 if (!dev) {
284 rte_errno = EINVAL;
285 return -rte_errno;
286 }
287 priv = dev->data->dev_private;
288 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
289 dev_link.link_speed = context_obj->mlx5_dev.link_speed / (1000 * 1000);
290 dev_link.link_status =
291 (context_obj->mlx5_dev.link_state == 1 && !mlx5_is_removed(dev))
292 ? 1 : 0;
293 dev_link.link_duplex = 1;
294 if (dev->data->dev_link.link_speed != dev_link.link_speed ||
295 dev->data->dev_link.link_duplex != dev_link.link_duplex ||
296 dev->data->dev_link.link_autoneg != dev_link.link_autoneg ||
297 dev->data->dev_link.link_status != dev_link.link_status)
298 ret = 1;
299 else
300 ret = 0;
301 dev->data->dev_link = dev_link;
302 return ret;
303 }
304
305 /**
306 * DPDK callback to bring the link DOWN.
307 *
308 * @param dev
309 * Pointer to Ethernet device structure.
310 *
311 * @return
312 * 0 on success, a negative errno value otherwise
313 */
314 int
mlx5_set_link_down(struct rte_eth_dev * dev)315 mlx5_set_link_down(struct rte_eth_dev *dev)
316 {
317 RTE_SET_USED(dev);
318 return -ENOTSUP;
319 }
320
321 /**
322 * DPDK callback to bring the link UP.
323 *
324 * @param dev
325 * Pointer to Ethernet device structure.
326 *
327 * @return
328 * 0 on success, a negative errno value otherwise
329 */
330 int
mlx5_set_link_up(struct rte_eth_dev * dev)331 mlx5_set_link_up(struct rte_eth_dev *dev)
332 {
333 RTE_SET_USED(dev);
334 return -ENOTSUP;
335 }
336
337 /**
338 * DPDK callback to retrieve plug-in module EEPROM information (type and size).
339 *
340 * @param dev
341 * Pointer to Ethernet device structure.
342 * @param[out] modinfo
343 * Storage for plug-in module EEPROM information.
344 *
345 * @return
346 * 0 on success, a negative errno value otherwise and rte_errno is set.
347 */
348 int
mlx5_get_module_info(struct rte_eth_dev * dev,struct rte_eth_dev_module_info * modinfo)349 mlx5_get_module_info(struct rte_eth_dev *dev,
350 struct rte_eth_dev_module_info *modinfo)
351 {
352 RTE_SET_USED(dev);
353 RTE_SET_USED(modinfo);
354 return -ENOTSUP;
355 }
356
357 /**
358 * DPDK callback to retrieve plug-in module EEPROM data.
359 *
360 * @param dev
361 * Pointer to Ethernet device structure.
362 * @param[out] info
363 * Storage for plug-in module EEPROM data.
364 *
365 * @return
366 * 0 on success, a negative errno value otherwise and rte_errno is set.
367 */
mlx5_get_module_eeprom(struct rte_eth_dev * dev,struct rte_dev_eeprom_info * info)368 int mlx5_get_module_eeprom(struct rte_eth_dev *dev,
369 struct rte_dev_eeprom_info *info)
370 {
371 RTE_SET_USED(dev);
372 RTE_SET_USED(info);
373 return -ENOTSUP;
374 }
375
376 /**
377 * Get device current raw clock counter
378 *
379 * @param dev
380 * Pointer to Ethernet device structure.
381 * @param[out] time
382 * Current raw clock counter of the device.
383 *
384 * @return
385 * 0 if the clock has correctly been read
386 * The value of errno in case of error
387 */
388 int
mlx5_read_clock(struct rte_eth_dev * dev,uint64_t * clock)389 mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
390 {
391 int err;
392 struct mlx5_devx_clock mlx5_clock;
393 struct mlx5_priv *priv = dev->data->dev_private;
394 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
395
396 err = mlx5_glue->query_rt_values(context_obj, &mlx5_clock);
397 if (err != 0) {
398 DRV_LOG(WARNING, "Could not query the clock");
399 return err;
400 }
401 *clock = *(uint64_t volatile *)mlx5_clock.p_iseg_internal_timer;
402 return 0;
403 }
404
405 /**
406 * Check if mlx5 device was removed.
407 *
408 * @param dev
409 * Pointer to Ethernet device structure.
410 *
411 * @return
412 * 1 when device is removed, otherwise 0.
413 */
414 int
mlx5_is_removed(struct rte_eth_dev * dev)415 mlx5_is_removed(struct rte_eth_dev *dev)
416 {
417 struct mlx5_priv *priv = dev->data->dev_private;
418 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx;
419
420 if (*context_obj->shutdown_event_obj.p_flag)
421 return 1;
422 return 0;
423 }
424
425 /*
426 * Query dropless_rq private flag value provided by ETHTOOL.
427 *
428 * @param dev
429 * Pointer to Ethernet device.
430 *
431 * @return
432 * - 0 on success, flag is not set.
433 * - 1 on success, flag is set.
434 * - negative errno value otherwise and rte_errno is set.
435 */
mlx5_get_flag_dropless_rq(struct rte_eth_dev * dev)436 int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev)
437 {
438 RTE_SET_USED(dev);
439 return -ENOTSUP;
440 }
441