Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2022 Advanced Micro Devices, Inc.
3 : : */
4 : :
5 : : #include <rte_ethdev.h>
6 : : #include <ethdev_driver.h>
7 : : #include <rte_malloc.h>
8 : :
9 : : #include "ionic_logs.h"
10 : : #include "ionic.h"
11 : : #include "ionic_dev.h"
12 : : #include "ionic_mac_api.h"
13 : : #include "ionic_lif.h"
14 : : #include "ionic_ethdev.h"
15 : : #include "ionic_rxtx.h"
16 : :
17 : : static int eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params);
18 : : static int eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev);
19 : : static int ionic_dev_info_get(struct rte_eth_dev *eth_dev,
20 : : struct rte_eth_dev_info *dev_info);
21 : : static int ionic_dev_configure(struct rte_eth_dev *dev);
22 : : static int ionic_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
23 : : static int ionic_dev_start(struct rte_eth_dev *dev);
24 : : static int ionic_dev_stop(struct rte_eth_dev *dev);
25 : : static int ionic_dev_close(struct rte_eth_dev *dev);
26 : : static int ionic_dev_set_link_up(struct rte_eth_dev *dev);
27 : : static int ionic_dev_set_link_down(struct rte_eth_dev *dev);
28 : : static int ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
29 : : struct rte_eth_fc_conf *fc_conf);
30 : : static int ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
31 : : struct rte_eth_fc_conf *fc_conf);
32 : : static int ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask);
33 : : static int ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev,
34 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size);
35 : : static int ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev,
36 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size);
37 : : static int ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
38 : : struct rte_eth_rss_conf *rss_conf);
39 : : static int ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,
40 : : struct rte_eth_rss_conf *rss_conf);
41 : : static int ionic_dev_stats_get(struct rte_eth_dev *eth_dev,
42 : : struct rte_eth_stats *stats);
43 : : static int ionic_dev_stats_reset(struct rte_eth_dev *eth_dev);
44 : : static int ionic_dev_xstats_get(struct rte_eth_dev *dev,
45 : : struct rte_eth_xstat *xstats, unsigned int n);
46 : : static int ionic_dev_xstats_get_by_id(struct rte_eth_dev *dev,
47 : : const uint64_t *ids, uint64_t *values, unsigned int n);
48 : : static int ionic_dev_xstats_reset(struct rte_eth_dev *dev);
49 : : static int ionic_dev_xstats_get_names(struct rte_eth_dev *dev,
50 : : struct rte_eth_xstat_name *xstats_names, unsigned int size);
51 : : static int ionic_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
52 : : const uint64_t *ids, struct rte_eth_xstat_name *xstats_names,
53 : : unsigned int limit);
54 : : static int ionic_dev_fw_version_get(struct rte_eth_dev *eth_dev,
55 : : char *fw_version, size_t fw_size);
56 : :
57 : : static const struct rte_eth_desc_lim rx_desc_lim = {
58 : : .nb_max = IONIC_MAX_RING_DESC,
59 : : .nb_min = IONIC_MIN_RING_DESC,
60 : : .nb_align = 1,
61 : : };
62 : :
63 : : static const struct rte_eth_desc_lim tx_desc_lim_v1 = {
64 : : .nb_max = IONIC_MAX_RING_DESC,
65 : : .nb_min = IONIC_MIN_RING_DESC,
66 : : .nb_align = 1,
67 : : .nb_seg_max = IONIC_TX_MAX_SG_ELEMS_V1 + 1,
68 : : .nb_mtu_seg_max = IONIC_TX_MAX_SG_ELEMS_V1 + 1,
69 : : };
70 : :
71 : : static const struct eth_dev_ops ionic_eth_dev_ops = {
72 : : .dev_infos_get = ionic_dev_info_get,
73 : : .dev_supported_ptypes_get = ionic_dev_supported_ptypes_get,
74 : : .dev_configure = ionic_dev_configure,
75 : : .mtu_set = ionic_dev_mtu_set,
76 : : .dev_start = ionic_dev_start,
77 : : .dev_stop = ionic_dev_stop,
78 : : .dev_close = ionic_dev_close,
79 : : .link_update = ionic_dev_link_update,
80 : : .dev_set_link_up = ionic_dev_set_link_up,
81 : : .dev_set_link_down = ionic_dev_set_link_down,
82 : : .mac_addr_add = ionic_dev_add_mac,
83 : : .mac_addr_remove = ionic_dev_remove_mac,
84 : : .mac_addr_set = ionic_dev_set_mac,
85 : : .vlan_filter_set = ionic_dev_vlan_filter_set,
86 : : .promiscuous_enable = ionic_dev_promiscuous_enable,
87 : : .promiscuous_disable = ionic_dev_promiscuous_disable,
88 : : .allmulticast_enable = ionic_dev_allmulticast_enable,
89 : : .allmulticast_disable = ionic_dev_allmulticast_disable,
90 : : .flow_ctrl_get = ionic_flow_ctrl_get,
91 : : .flow_ctrl_set = ionic_flow_ctrl_set,
92 : : .rxq_info_get = ionic_rxq_info_get,
93 : : .txq_info_get = ionic_txq_info_get,
94 : : .rx_queue_setup = ionic_dev_rx_queue_setup,
95 : : .rx_queue_release = ionic_dev_rx_queue_release,
96 : : .rx_queue_start = ionic_dev_rx_queue_start,
97 : : .rx_queue_stop = ionic_dev_rx_queue_stop,
98 : : .tx_queue_setup = ionic_dev_tx_queue_setup,
99 : : .tx_queue_release = ionic_dev_tx_queue_release,
100 : : .tx_queue_start = ionic_dev_tx_queue_start,
101 : : .tx_queue_stop = ionic_dev_tx_queue_stop,
102 : : .vlan_offload_set = ionic_vlan_offload_set,
103 : : .reta_update = ionic_dev_rss_reta_update,
104 : : .reta_query = ionic_dev_rss_reta_query,
105 : : .rss_hash_conf_get = ionic_dev_rss_hash_conf_get,
106 : : .rss_hash_update = ionic_dev_rss_hash_update,
107 : : .stats_get = ionic_dev_stats_get,
108 : : .stats_reset = ionic_dev_stats_reset,
109 : : .xstats_get = ionic_dev_xstats_get,
110 : : .xstats_get_by_id = ionic_dev_xstats_get_by_id,
111 : : .xstats_reset = ionic_dev_xstats_reset,
112 : : .xstats_get_names = ionic_dev_xstats_get_names,
113 : : .xstats_get_names_by_id = ionic_dev_xstats_get_names_by_id,
114 : : .fw_version_get = ionic_dev_fw_version_get,
115 : : };
116 : :
117 : : struct rte_ionic_xstats_name_off {
118 : : char name[RTE_ETH_XSTATS_NAME_SIZE];
119 : : unsigned int offset;
120 : : };
121 : :
122 : : static const struct rte_ionic_xstats_name_off rte_ionic_xstats_strings[] = {
123 : : /* RX */
124 : : {"rx_ucast_bytes", offsetof(struct ionic_lif_stats,
125 : : rx_ucast_bytes)},
126 : : {"rx_ucast_packets", offsetof(struct ionic_lif_stats,
127 : : rx_ucast_packets)},
128 : : {"rx_mcast_bytes", offsetof(struct ionic_lif_stats,
129 : : rx_mcast_bytes)},
130 : : {"rx_mcast_packets", offsetof(struct ionic_lif_stats,
131 : : rx_mcast_packets)},
132 : : {"rx_bcast_bytes", offsetof(struct ionic_lif_stats,
133 : : rx_bcast_bytes)},
134 : : {"rx_bcast_packets", offsetof(struct ionic_lif_stats,
135 : : rx_bcast_packets)},
136 : : /* RX drops */
137 : : {"rx_ucast_drop_bytes", offsetof(struct ionic_lif_stats,
138 : : rx_ucast_drop_bytes)},
139 : : {"rx_ucast_drop_packets", offsetof(struct ionic_lif_stats,
140 : : rx_ucast_drop_packets)},
141 : : {"rx_mcast_drop_bytes", offsetof(struct ionic_lif_stats,
142 : : rx_mcast_drop_bytes)},
143 : : {"rx_mcast_drop_packets", offsetof(struct ionic_lif_stats,
144 : : rx_mcast_drop_packets)},
145 : : {"rx_bcast_drop_bytes", offsetof(struct ionic_lif_stats,
146 : : rx_bcast_drop_bytes)},
147 : : {"rx_bcast_drop_packets", offsetof(struct ionic_lif_stats,
148 : : rx_bcast_drop_packets)},
149 : : {"rx_dma_error", offsetof(struct ionic_lif_stats,
150 : : rx_dma_error)},
151 : : /* TX */
152 : : {"tx_ucast_bytes", offsetof(struct ionic_lif_stats,
153 : : tx_ucast_bytes)},
154 : : {"tx_ucast_packets", offsetof(struct ionic_lif_stats,
155 : : tx_ucast_packets)},
156 : : {"tx_mcast_bytes", offsetof(struct ionic_lif_stats,
157 : : tx_mcast_bytes)},
158 : : {"tx_mcast_packets", offsetof(struct ionic_lif_stats,
159 : : tx_mcast_packets)},
160 : : {"tx_bcast_bytes", offsetof(struct ionic_lif_stats,
161 : : tx_bcast_bytes)},
162 : : {"tx_bcast_packets", offsetof(struct ionic_lif_stats,
163 : : tx_bcast_packets)},
164 : : /* TX drops */
165 : : {"tx_ucast_drop_bytes", offsetof(struct ionic_lif_stats,
166 : : tx_ucast_drop_bytes)},
167 : : {"tx_ucast_drop_packets", offsetof(struct ionic_lif_stats,
168 : : tx_ucast_drop_packets)},
169 : : {"tx_mcast_drop_bytes", offsetof(struct ionic_lif_stats,
170 : : tx_mcast_drop_bytes)},
171 : : {"tx_mcast_drop_packets", offsetof(struct ionic_lif_stats,
172 : : tx_mcast_drop_packets)},
173 : : {"tx_bcast_drop_bytes", offsetof(struct ionic_lif_stats,
174 : : tx_bcast_drop_bytes)},
175 : : {"tx_bcast_drop_packets", offsetof(struct ionic_lif_stats,
176 : : tx_bcast_drop_packets)},
177 : : {"tx_dma_error", offsetof(struct ionic_lif_stats,
178 : : tx_dma_error)},
179 : : /* Rx Queue/Ring drops */
180 : : {"rx_queue_disabled", offsetof(struct ionic_lif_stats,
181 : : rx_queue_disabled)},
182 : : {"rx_queue_empty", offsetof(struct ionic_lif_stats,
183 : : rx_queue_empty)},
184 : : {"rx_queue_error", offsetof(struct ionic_lif_stats,
185 : : rx_queue_error)},
186 : : {"rx_desc_fetch_error", offsetof(struct ionic_lif_stats,
187 : : rx_desc_fetch_error)},
188 : : {"rx_desc_data_error", offsetof(struct ionic_lif_stats,
189 : : rx_desc_data_error)},
190 : : /* Tx Queue/Ring drops */
191 : : {"tx_queue_disabled", offsetof(struct ionic_lif_stats,
192 : : tx_queue_disabled)},
193 : : {"tx_queue_error", offsetof(struct ionic_lif_stats,
194 : : tx_queue_error)},
195 : : {"tx_desc_fetch_error", offsetof(struct ionic_lif_stats,
196 : : tx_desc_fetch_error)},
197 : : {"tx_desc_data_error", offsetof(struct ionic_lif_stats,
198 : : tx_desc_data_error)},
199 : : };
200 : :
201 : : #define IONIC_NB_HW_STATS RTE_DIM(rte_ionic_xstats_strings)
202 : :
203 : : static int
204 : 0 : ionic_dev_fw_version_get(struct rte_eth_dev *eth_dev,
205 : : char *fw_version, size_t fw_size)
206 : : {
207 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
208 : 0 : struct ionic_adapter *adapter = lif->adapter;
209 : : int ret;
210 : :
211 : : ret = snprintf(fw_version, fw_size, "%s",
212 [ # # ]: 0 : adapter->fw_version);
213 [ # # ]: 0 : if (ret < 0)
214 : : return -EINVAL;
215 : :
216 : 0 : ret += 1; /* add the size of '\0' */
217 [ # # ]: 0 : if (fw_size < (size_t)ret)
218 : : return ret;
219 : : else
220 : 0 : return 0;
221 : : }
222 : :
223 : : /*
224 : : * Set device link up, enable tx.
225 : : */
226 : : static int
227 : 0 : ionic_dev_set_link_up(struct rte_eth_dev *eth_dev)
228 : : {
229 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
230 : : int err;
231 : :
232 : 0 : IONIC_PRINT_CALL();
233 : :
234 : 0 : err = ionic_lif_start(lif);
235 [ # # ]: 0 : if (err)
236 : 0 : IONIC_PRINT(ERR, "Could not start lif to set link up");
237 : :
238 : 0 : ionic_dev_link_update(lif->eth_dev, 0);
239 : :
240 : 0 : return err;
241 : : }
242 : :
243 : : /*
244 : : * Set device link down, disable tx.
245 : : */
246 : : static int
247 : 0 : ionic_dev_set_link_down(struct rte_eth_dev *eth_dev)
248 : : {
249 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
250 : :
251 : 0 : IONIC_PRINT_CALL();
252 : :
253 : 0 : ionic_lif_stop(lif);
254 : :
255 : 0 : ionic_dev_link_update(lif->eth_dev, 0);
256 : :
257 : 0 : return 0;
258 : : }
259 : :
260 : : int
261 : 0 : ionic_dev_link_update(struct rte_eth_dev *eth_dev,
262 : : int wait_to_complete __rte_unused)
263 : : {
264 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
265 : 0 : struct ionic_adapter *adapter = lif->adapter;
266 : : struct rte_eth_link link;
267 : :
268 : 0 : IONIC_PRINT_CALL();
269 : :
270 : : /* Initialize */
271 : : memset(&link, 0, sizeof(link));
272 : :
273 [ # # ]: 0 : if (adapter->idev.port_info->config.an_enable) {
274 : 0 : link.link_autoneg = RTE_ETH_LINK_AUTONEG;
275 : : }
276 : :
277 [ # # ]: 0 : if (!adapter->link_up ||
278 [ # # ]: 0 : !(lif->state & IONIC_LIF_F_UP)) {
279 : : /* Interface is down */
280 : : link.link_status = RTE_ETH_LINK_DOWN;
281 : : link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
282 : : link.link_speed = RTE_ETH_SPEED_NUM_NONE;
283 : : } else {
284 : : /* Interface is up */
285 : 0 : link.link_status = RTE_ETH_LINK_UP;
286 : 0 : link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
287 [ # # # # : 0 : switch (adapter->link_speed) {
# # ]
288 : 0 : case 10000:
289 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_10G;
290 : 0 : break;
291 : 0 : case 25000:
292 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_25G;
293 : 0 : break;
294 : 0 : case 40000:
295 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_40G;
296 : 0 : break;
297 : 0 : case 50000:
298 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_50G;
299 : 0 : break;
300 : 0 : case 100000:
301 : 0 : link.link_speed = RTE_ETH_SPEED_NUM_100G;
302 : 0 : break;
303 : : default:
304 : : link.link_speed = RTE_ETH_SPEED_NUM_NONE;
305 : : break;
306 : : }
307 : : }
308 : :
309 : 0 : return rte_eth_linkstatus_set(eth_dev, &link);
310 : : }
311 : :
312 : : /**
313 : : * Interrupt handler triggered by NIC for handling
314 : : * specific interrupt.
315 : : *
316 : : * @param param
317 : : * The address of parameter registered before.
318 : : *
319 : : * @return
320 : : * void
321 : : */
322 : : void
323 : 0 : ionic_dev_interrupt_handler(void *param)
324 : : {
325 : : struct ionic_adapter *adapter = (struct ionic_adapter *)param;
326 : :
327 : 0 : IONIC_PRINT(DEBUG, "->");
328 : :
329 [ # # ]: 0 : if (adapter->lif)
330 : 0 : ionic_notifyq_handler(adapter->lif, -1);
331 : 0 : }
332 : :
333 : : static int
334 : 0 : ionic_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
335 : : {
336 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
337 : :
338 [ # # ]: 0 : if (lif->state & IONIC_LIF_F_UP) {
339 : 0 : IONIC_PRINT(ERR, "Stop %s before setting mtu", lif->name);
340 : 0 : return -EBUSY;
341 : : }
342 : :
343 : : /* Note: mtu check against min/max is done by the API */
344 : 0 : IONIC_PRINT(INFO, "Setting mtu %u", mtu);
345 : :
346 : : /* Update the frame size used by the Rx path */
347 : 0 : lif->frame_size = mtu + IONIC_ETH_OVERHEAD;
348 : :
349 : 0 : return 0;
350 : : }
351 : :
352 : : static int
353 : 0 : ionic_dev_info_get(struct rte_eth_dev *eth_dev,
354 : : struct rte_eth_dev_info *dev_info)
355 : : {
356 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
357 : 0 : struct ionic_adapter *adapter = lif->adapter;
358 : : struct ionic_identity *ident = &adapter->ident;
359 : : union ionic_lif_config *cfg = &ident->lif.eth.config;
360 : :
361 : 0 : IONIC_PRINT_CALL();
362 : :
363 : 0 : dev_info->max_rx_queues = (uint16_t)
364 : 0 : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_RXQ]);
365 : 0 : dev_info->max_tx_queues = (uint16_t)
366 : 0 : rte_le_to_cpu_32(cfg->queue_count[IONIC_QTYPE_TXQ]);
367 : :
368 : : /* Also add ETHER_CRC_LEN if the adapter is able to keep CRC */
369 : 0 : dev_info->min_mtu = RTE_MAX((uint32_t)IONIC_MIN_MTU,
370 : : rte_le_to_cpu_32(ident->lif.eth.min_mtu));
371 : 0 : dev_info->max_mtu = RTE_MIN((uint32_t)IONIC_MAX_MTU,
372 : : rte_le_to_cpu_32(ident->lif.eth.max_mtu));
373 : 0 : dev_info->min_rx_bufsize = dev_info->min_mtu + IONIC_ETH_OVERHEAD;
374 : 0 : dev_info->max_rx_pktlen = dev_info->max_mtu + IONIC_ETH_OVERHEAD;
375 : 0 : dev_info->max_lro_pkt_size =
376 : 0 : eth_dev->data->dev_conf.rxmode.max_lro_pkt_size;
377 : :
378 : 0 : dev_info->max_mac_addrs = adapter->max_mac_addrs;
379 : 0 : dev_info->hash_key_size = IONIC_RSS_HASH_KEY_SIZE;
380 : 0 : dev_info->reta_size = rte_le_to_cpu_16(ident->lif.eth.rss_ind_tbl_sz);
381 : 0 : dev_info->flow_type_rss_offloads = IONIC_ETH_RSS_OFFLOAD_ALL;
382 : :
383 : 0 : dev_info->speed_capa =
384 : : RTE_ETH_LINK_SPEED_10G |
385 : : RTE_ETH_LINK_SPEED_25G |
386 : : RTE_ETH_LINK_SPEED_40G |
387 : : RTE_ETH_LINK_SPEED_50G |
388 : : RTE_ETH_LINK_SPEED_100G;
389 : :
390 : : /*
391 : : * Per-queue capabilities
392 : : * RTE does not support disabling a feature on a queue if it is
393 : : * enabled globally on the device. Thus the driver does not advertise
394 : : * capabilities like RTE_ETH_TX_OFFLOAD_IPV4_CKSUM as per-queue even
395 : : * though the driver would be otherwise capable of disabling it on
396 : : * a per-queue basis.
397 : : */
398 : :
399 : 0 : dev_info->rx_queue_offload_capa = 0;
400 : 0 : dev_info->tx_queue_offload_capa = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
401 : :
402 : : /*
403 : : * Per-port capabilities
404 : : * See ionic_set_features to request and check supported features
405 : : */
406 : :
407 : 0 : dev_info->rx_offload_capa = dev_info->rx_queue_offload_capa |
408 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
409 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
410 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
411 : : RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
412 : : RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
413 : : RTE_ETH_RX_OFFLOAD_SCATTER |
414 : : RTE_ETH_RX_OFFLOAD_RSS_HASH |
415 : : 0;
416 : :
417 : 0 : dev_info->tx_offload_capa = dev_info->tx_queue_offload_capa |
418 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
419 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
420 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
421 : : RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
422 : : RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |
423 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
424 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
425 : : RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
426 : : 0;
427 : :
428 : 0 : dev_info->rx_desc_lim = rx_desc_lim;
429 : 0 : dev_info->tx_desc_lim = tx_desc_lim_v1;
430 : :
431 : : /* Driver-preferred Rx/Tx parameters */
432 : 0 : dev_info->default_rxportconf.burst_size = IONIC_DEF_TXRX_BURST;
433 : 0 : dev_info->default_txportconf.burst_size = IONIC_DEF_TXRX_BURST;
434 : 0 : dev_info->default_rxportconf.nb_queues = 1;
435 : 0 : dev_info->default_txportconf.nb_queues = 1;
436 : 0 : dev_info->default_rxportconf.ring_size = IONIC_DEF_TXRX_DESC;
437 : 0 : dev_info->default_txportconf.ring_size = IONIC_DEF_TXRX_DESC;
438 : :
439 : 0 : dev_info->default_rxconf = (struct rte_eth_rxconf) {
440 : : /* Packets are always dropped if no desc are available */
441 : : .rx_drop_en = 1,
442 : : };
443 : :
444 : 0 : return 0;
445 : : }
446 : :
447 : : static int
448 : 0 : ionic_flow_ctrl_get(struct rte_eth_dev *eth_dev,
449 : : struct rte_eth_fc_conf *fc_conf)
450 : : {
451 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
452 : 0 : struct ionic_adapter *adapter = lif->adapter;
453 : : struct ionic_dev *idev = &adapter->idev;
454 : :
455 [ # # ]: 0 : if (idev->port_info) {
456 : : /* Flow control autoneg not supported */
457 : 0 : fc_conf->autoneg = 0;
458 : :
459 [ # # ]: 0 : if (idev->port_info->config.pause_type)
460 : 0 : fc_conf->mode = RTE_ETH_FC_FULL;
461 : : else
462 : 0 : fc_conf->mode = RTE_ETH_FC_NONE;
463 : : }
464 : :
465 : 0 : return 0;
466 : : }
467 : :
468 : : static int
469 : 0 : ionic_flow_ctrl_set(struct rte_eth_dev *eth_dev,
470 : : struct rte_eth_fc_conf *fc_conf)
471 : : {
472 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
473 : 0 : struct ionic_adapter *adapter = lif->adapter;
474 : 0 : struct ionic_dev *idev = &adapter->idev;
475 : : uint8_t pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
476 : : int err;
477 : :
478 [ # # ]: 0 : if (fc_conf->autoneg) {
479 : 0 : IONIC_PRINT(WARNING, "Flow control autoneg not supported");
480 : 0 : return -ENOTSUP;
481 : : }
482 : :
483 [ # # # ]: 0 : switch (fc_conf->mode) {
484 : : case RTE_ETH_FC_NONE:
485 : : pause_type = IONIC_PORT_PAUSE_TYPE_NONE;
486 : : break;
487 : 0 : case RTE_ETH_FC_FULL:
488 : : pause_type = IONIC_PORT_PAUSE_TYPE_LINK;
489 : 0 : break;
490 : : case RTE_ETH_FC_RX_PAUSE:
491 : : case RTE_ETH_FC_TX_PAUSE:
492 : : return -ENOTSUP;
493 : : }
494 : :
495 : 0 : ionic_dev_cmd_port_pause(idev, pause_type);
496 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
497 [ # # ]: 0 : if (err)
498 : 0 : IONIC_PRINT(WARNING, "Failed to configure flow control");
499 : :
500 : : return err;
501 : : }
502 : :
503 : : static int
504 : 0 : ionic_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
505 : : {
506 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
507 : :
508 : 0 : ionic_lif_configure_vlan_offload(lif, mask);
509 : :
510 : 0 : ionic_lif_set_features(lif);
511 : :
512 : 0 : return 0;
513 : : }
514 : :
515 : : static int
516 : 0 : ionic_dev_rss_reta_update(struct rte_eth_dev *eth_dev,
517 : : struct rte_eth_rss_reta_entry64 *reta_conf,
518 : : uint16_t reta_size)
519 : : {
520 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
521 : 0 : struct ionic_adapter *adapter = lif->adapter;
522 : : struct ionic_identity *ident = &adapter->ident;
523 : : uint32_t i, j, index, num;
524 : 0 : uint16_t tbl_sz = rte_le_to_cpu_16(ident->lif.eth.rss_ind_tbl_sz);
525 : :
526 : 0 : IONIC_PRINT_CALL();
527 : :
528 [ # # ]: 0 : if (!lif->rss_ind_tbl) {
529 : 0 : IONIC_PRINT(ERR, "RSS RETA not initialized, "
530 : : "can't update the table");
531 : 0 : return -EINVAL;
532 : : }
533 : :
534 [ # # ]: 0 : if (reta_size != tbl_sz) {
535 : 0 : IONIC_PRINT(ERR, "The size of hash lookup table configured "
536 : : "(%d) does not match the number hardware can support "
537 : : "(%d)",
538 : : reta_size, tbl_sz);
539 : 0 : return -EINVAL;
540 : : }
541 : :
542 : 0 : num = tbl_sz / RTE_ETH_RETA_GROUP_SIZE;
543 : :
544 [ # # ]: 0 : for (i = 0; i < num; i++) {
545 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++) {
546 [ # # ]: 0 : if (reta_conf[i].mask & ((uint64_t)1 << j)) {
547 : 0 : index = (i * RTE_ETH_RETA_GROUP_SIZE) + j;
548 : 0 : lif->rss_ind_tbl[index] = reta_conf[i].reta[j];
549 : : }
550 : : }
551 : : }
552 : :
553 : 0 : return ionic_lif_rss_config(lif, lif->rss_types, NULL, NULL);
554 : : }
555 : :
556 : : static int
557 : 0 : ionic_dev_rss_reta_query(struct rte_eth_dev *eth_dev,
558 : : struct rte_eth_rss_reta_entry64 *reta_conf,
559 : : uint16_t reta_size)
560 : : {
561 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
562 : 0 : struct ionic_adapter *adapter = lif->adapter;
563 : : struct ionic_identity *ident = &adapter->ident;
564 : : int i, num;
565 : 0 : uint16_t tbl_sz = rte_le_to_cpu_16(ident->lif.eth.rss_ind_tbl_sz);
566 : :
567 : 0 : IONIC_PRINT_CALL();
568 : :
569 [ # # ]: 0 : if (reta_size != tbl_sz) {
570 : 0 : IONIC_PRINT(ERR, "The size of hash lookup table configured "
571 : : "(%d) does not match the number hardware can support "
572 : : "(%d)",
573 : : reta_size, tbl_sz);
574 : 0 : return -EINVAL;
575 : : }
576 : :
577 [ # # ]: 0 : if (!lif->rss_ind_tbl) {
578 : 0 : IONIC_PRINT(ERR, "RSS RETA has not been built yet");
579 : 0 : return -EINVAL;
580 : : }
581 : :
582 : 0 : num = reta_size / RTE_ETH_RETA_GROUP_SIZE;
583 : :
584 [ # # ]: 0 : for (i = 0; i < num; i++) {
585 : 0 : memcpy(reta_conf->reta,
586 : 0 : &lif->rss_ind_tbl[i * RTE_ETH_RETA_GROUP_SIZE],
587 : : RTE_ETH_RETA_GROUP_SIZE);
588 : 0 : reta_conf++;
589 : : }
590 : :
591 : : return 0;
592 : : }
593 : :
594 : : static int
595 : 0 : ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
596 : : struct rte_eth_rss_conf *rss_conf)
597 : : {
598 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
599 : : uint64_t rss_hf = 0;
600 : :
601 : 0 : IONIC_PRINT_CALL();
602 : :
603 [ # # ]: 0 : if (!lif->rss_ind_tbl) {
604 : 0 : IONIC_PRINT(NOTICE, "RSS not enabled");
605 : 0 : return 0;
606 : : }
607 : :
608 : : /* Get key value (if not null, rss_key is 40-byte) */
609 [ # # ]: 0 : if (rss_conf->rss_key != NULL &&
610 [ # # ]: 0 : rss_conf->rss_key_len >= IONIC_RSS_HASH_KEY_SIZE)
611 : 0 : memcpy(rss_conf->rss_key, lif->rss_hash_key,
612 : : IONIC_RSS_HASH_KEY_SIZE);
613 : :
614 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV4)
615 : : rss_hf |= RTE_ETH_RSS_IPV4;
616 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV4_TCP)
617 : 0 : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
618 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV4_UDP)
619 : 0 : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
620 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV6)
621 : 0 : rss_hf |= RTE_ETH_RSS_IPV6;
622 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV6_TCP)
623 : 0 : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
624 [ # # ]: 0 : if (lif->rss_types & IONIC_RSS_TYPE_IPV6_UDP)
625 : 0 : rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
626 : :
627 : 0 : rss_conf->rss_hf = rss_hf;
628 : :
629 : 0 : return 0;
630 : : }
631 : :
632 : : static int
633 : 0 : ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,
634 : : struct rte_eth_rss_conf *rss_conf)
635 : : {
636 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
637 : : uint32_t rss_types = 0;
638 : : uint8_t *key = NULL;
639 : :
640 : 0 : IONIC_PRINT_CALL();
641 : :
642 [ # # ]: 0 : if (rss_conf->rss_key)
643 : : key = rss_conf->rss_key;
644 : :
645 [ # # ]: 0 : if ((rss_conf->rss_hf & IONIC_ETH_RSS_OFFLOAD_ALL) == 0) {
646 : : /*
647 : : * Can't disable rss through hash flags,
648 : : * if it is enabled by default during init
649 : : */
650 [ # # ]: 0 : if (lif->rss_ind_tbl)
651 : 0 : return -EINVAL;
652 : : } else {
653 : : /* Can't enable rss if disabled by default during init */
654 [ # # ]: 0 : if (!lif->rss_ind_tbl)
655 : : return -EINVAL;
656 : :
657 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_IPV4)
658 : : rss_types |= IONIC_RSS_TYPE_IPV4;
659 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP)
660 : 0 : rss_types |= IONIC_RSS_TYPE_IPV4_TCP;
661 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP)
662 : 0 : rss_types |= IONIC_RSS_TYPE_IPV4_UDP;
663 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_IPV6)
664 : 0 : rss_types |= IONIC_RSS_TYPE_IPV6;
665 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP)
666 : 0 : rss_types |= IONIC_RSS_TYPE_IPV6_TCP;
667 [ # # ]: 0 : if (rss_conf->rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP)
668 : 0 : rss_types |= IONIC_RSS_TYPE_IPV6_UDP;
669 : :
670 : 0 : ionic_lif_rss_config(lif, rss_types, key, NULL);
671 : : }
672 : :
673 : : return 0;
674 : : }
675 : :
676 : : static int
677 : 0 : ionic_dev_stats_get(struct rte_eth_dev *eth_dev,
678 : : struct rte_eth_stats *stats)
679 : : {
680 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
681 : :
682 : 0 : ionic_lif_get_stats(lif, stats);
683 : :
684 : 0 : return 0;
685 : : }
686 : :
687 : : static int
688 : 0 : ionic_dev_stats_reset(struct rte_eth_dev *eth_dev)
689 : : {
690 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
691 : :
692 : 0 : IONIC_PRINT_CALL();
693 : :
694 : 0 : ionic_lif_reset_stats(lif);
695 : :
696 : 0 : return 0;
697 : : }
698 : :
699 : : static int
700 : 0 : ionic_dev_xstats_get_names(__rte_unused struct rte_eth_dev *eth_dev,
701 : : struct rte_eth_xstat_name *xstats_names,
702 : : __rte_unused unsigned int size)
703 : : {
704 : : unsigned int i;
705 : :
706 [ # # ]: 0 : if (xstats_names != NULL) {
707 [ # # ]: 0 : for (i = 0; i < IONIC_NB_HW_STATS; i++) {
708 : 0 : snprintf(xstats_names[i].name,
709 : : sizeof(xstats_names[i].name),
710 : 0 : "%s", rte_ionic_xstats_strings[i].name);
711 : : }
712 : : }
713 : :
714 : 0 : return IONIC_NB_HW_STATS;
715 : : }
716 : :
717 : : static int
718 : 0 : ionic_dev_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
719 : : const uint64_t *ids, struct rte_eth_xstat_name *xstats_names,
720 : : unsigned int limit)
721 : : {
722 : : struct rte_eth_xstat_name xstats_names_copy[IONIC_NB_HW_STATS];
723 : : uint16_t i;
724 : :
725 [ # # ]: 0 : if (!ids) {
726 [ # # ]: 0 : if (xstats_names != NULL) {
727 [ # # ]: 0 : for (i = 0; i < IONIC_NB_HW_STATS; i++) {
728 : 0 : snprintf(xstats_names[i].name,
729 : : sizeof(xstats_names[i].name),
730 : 0 : "%s", rte_ionic_xstats_strings[i].name);
731 : : }
732 : : }
733 : :
734 : 0 : return IONIC_NB_HW_STATS;
735 : : }
736 : :
737 : 0 : ionic_dev_xstats_get_names_by_id(eth_dev, NULL, xstats_names_copy,
738 : : IONIC_NB_HW_STATS);
739 : :
740 [ # # ]: 0 : for (i = 0; i < limit; i++) {
741 [ # # ]: 0 : if (ids[i] >= IONIC_NB_HW_STATS) {
742 : 0 : IONIC_PRINT(ERR, "id value isn't valid");
743 : 0 : return -1;
744 : : }
745 : :
746 : 0 : strcpy(xstats_names[i].name, xstats_names_copy[ids[i]].name);
747 : : }
748 : :
749 : 0 : return limit;
750 : : }
751 : :
752 : : static int
753 : 0 : ionic_dev_xstats_get(struct rte_eth_dev *eth_dev, struct rte_eth_xstat *xstats,
754 : : unsigned int n)
755 : : {
756 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
757 : : struct ionic_lif_stats hw_stats;
758 : : uint16_t i;
759 : :
760 [ # # ]: 0 : if (n < IONIC_NB_HW_STATS)
761 : : return IONIC_NB_HW_STATS;
762 : :
763 : 0 : ionic_lif_get_hw_stats(lif, &hw_stats);
764 : :
765 [ # # ]: 0 : for (i = 0; i < IONIC_NB_HW_STATS; i++) {
766 : 0 : xstats[i].value = *(uint64_t *)(((char *)&hw_stats) +
767 : 0 : rte_ionic_xstats_strings[i].offset);
768 : 0 : xstats[i].id = i;
769 : : }
770 : :
771 : : return IONIC_NB_HW_STATS;
772 : : }
773 : :
774 : : static int
775 : 0 : ionic_dev_xstats_get_by_id(struct rte_eth_dev *eth_dev, const uint64_t *ids,
776 : : uint64_t *values, unsigned int n)
777 : : {
778 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
779 : : struct ionic_lif_stats hw_stats;
780 : : uint64_t values_copy[IONIC_NB_HW_STATS];
781 : : uint16_t i;
782 : :
783 [ # # ]: 0 : if (!ids) {
784 [ # # ]: 0 : if (!ids && n < IONIC_NB_HW_STATS)
785 : : return IONIC_NB_HW_STATS;
786 : :
787 : 0 : ionic_lif_get_hw_stats(lif, &hw_stats);
788 : :
789 [ # # ]: 0 : for (i = 0; i < IONIC_NB_HW_STATS; i++) {
790 : 0 : values[i] = *(uint64_t *)(((char *)&hw_stats) +
791 : 0 : rte_ionic_xstats_strings[i].offset);
792 : : }
793 : :
794 : : return IONIC_NB_HW_STATS;
795 : : }
796 : :
797 : 0 : ionic_dev_xstats_get_by_id(eth_dev, NULL, values_copy,
798 : : IONIC_NB_HW_STATS);
799 : :
800 [ # # ]: 0 : for (i = 0; i < n; i++) {
801 [ # # ]: 0 : if (ids[i] >= IONIC_NB_HW_STATS) {
802 : 0 : IONIC_PRINT(ERR, "id value isn't valid");
803 : 0 : return -1;
804 : : }
805 : :
806 : 0 : values[i] = values_copy[ids[i]];
807 : : }
808 : :
809 : 0 : return n;
810 : : }
811 : :
812 : : static int
813 : 0 : ionic_dev_xstats_reset(struct rte_eth_dev *eth_dev)
814 : : {
815 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
816 : :
817 : 0 : ionic_lif_reset_hw_stats(lif);
818 : :
819 : 0 : return 0;
820 : : }
821 : :
822 : : static int
823 : 0 : ionic_dev_configure(struct rte_eth_dev *eth_dev)
824 : : {
825 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
826 : :
827 : 0 : IONIC_PRINT_CALL();
828 : :
829 : 0 : ionic_lif_configure(lif);
830 : :
831 : 0 : return 0;
832 : : }
833 : :
834 : : static inline uint32_t
835 : : ionic_parse_link_speeds(uint16_t link_speeds)
836 : : {
837 : 0 : if (link_speeds & RTE_ETH_LINK_SPEED_100G)
838 : : return 100000;
839 [ # # ]: 0 : else if (link_speeds & RTE_ETH_LINK_SPEED_50G)
840 : : return 50000;
841 [ # # ]: 0 : else if (link_speeds & RTE_ETH_LINK_SPEED_40G)
842 : : return 40000;
843 [ # # ]: 0 : else if (link_speeds & RTE_ETH_LINK_SPEED_25G)
844 : : return 25000;
845 [ # # ]: 0 : else if (link_speeds & RTE_ETH_LINK_SPEED_10G)
846 : : return 10000;
847 : : else
848 : : return 0;
849 : : }
850 : :
851 : : /*
852 : : * Configure device link speed and setup link.
853 : : * It returns 0 on success.
854 : : */
855 : : static int
856 : 0 : ionic_dev_start(struct rte_eth_dev *eth_dev)
857 : : {
858 : 0 : struct rte_eth_conf *dev_conf = ð_dev->data->dev_conf;
859 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
860 : 0 : struct ionic_adapter *adapter = lif->adapter;
861 : 0 : struct ionic_dev *idev = &adapter->idev;
862 : : uint32_t speed = 0, allowed_speeds;
863 : : uint8_t an_enable;
864 : : int err;
865 : :
866 : 0 : IONIC_PRINT_CALL();
867 : :
868 : : allowed_speeds =
869 : : RTE_ETH_LINK_SPEED_FIXED |
870 : : RTE_ETH_LINK_SPEED_10G |
871 : : RTE_ETH_LINK_SPEED_25G |
872 : : RTE_ETH_LINK_SPEED_40G |
873 : : RTE_ETH_LINK_SPEED_50G |
874 : : RTE_ETH_LINK_SPEED_100G;
875 : :
876 [ # # ]: 0 : if (dev_conf->link_speeds & ~allowed_speeds) {
877 : 0 : IONIC_PRINT(ERR, "Invalid link setting");
878 : 0 : return -EINVAL;
879 : : }
880 : :
881 [ # # ]: 0 : if (dev_conf->lpbk_mode)
882 : 0 : IONIC_PRINT(WARNING, "Loopback mode not supported");
883 : :
884 : : /* Re-set features in case SG flag was added in rx_queue_setup() */
885 : 0 : err = ionic_lif_set_features(lif);
886 [ # # ]: 0 : if (err) {
887 : 0 : IONIC_PRINT(ERR, "Cannot set LIF features: %d", err);
888 : 0 : return err;
889 : : }
890 : :
891 : 0 : lif->frame_size = eth_dev->data->mtu + IONIC_ETH_OVERHEAD;
892 : :
893 : 0 : err = ionic_lif_change_mtu(lif, eth_dev->data->mtu);
894 [ # # ]: 0 : if (err) {
895 : 0 : IONIC_PRINT(ERR, "Cannot set LIF frame size %u: %d",
896 : : lif->frame_size, err);
897 : 0 : return err;
898 : : }
899 : :
900 : 0 : err = ionic_lif_start(lif);
901 [ # # ]: 0 : if (err) {
902 : 0 : IONIC_PRINT(ERR, "Cannot start LIF: %d", err);
903 : 0 : return err;
904 : : }
905 : :
906 : : /* Configure link */
907 : 0 : an_enable = (dev_conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) == 0;
908 : :
909 : 0 : ionic_dev_cmd_port_autoneg(idev, an_enable);
910 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
911 [ # # ]: 0 : if (err)
912 [ # # ]: 0 : IONIC_PRINT(WARNING, "Failed to %s autonegotiation",
913 : : an_enable ? "enable" : "disable");
914 : :
915 [ # # ]: 0 : if (!an_enable)
916 [ # # ]: 0 : speed = ionic_parse_link_speeds(dev_conf->link_speeds);
917 : : if (speed) {
918 : 0 : ionic_dev_cmd_port_speed(idev, speed);
919 : 0 : err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);
920 [ # # ]: 0 : if (err)
921 : 0 : IONIC_PRINT(WARNING, "Failed to set link speed %u",
922 : : speed);
923 : : }
924 : :
925 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_RX_SG)
926 : 0 : eth_dev->rx_pkt_burst = &ionic_recv_pkts_sg;
927 : : else
928 : 0 : eth_dev->rx_pkt_burst = &ionic_recv_pkts;
929 : :
930 [ # # ]: 0 : if (lif->hw_features & IONIC_ETH_HW_TX_SG)
931 : 0 : eth_dev->tx_pkt_burst = &ionic_xmit_pkts_sg;
932 : : else
933 : 0 : eth_dev->tx_pkt_burst = &ionic_xmit_pkts;
934 : :
935 : 0 : eth_dev->tx_pkt_prepare = &ionic_prep_pkts;
936 : :
937 : 0 : ionic_dev_link_update(eth_dev, 0);
938 : :
939 : 0 : return 0;
940 : : }
941 : :
942 : : /*
943 : : * Stop device: disable rx and tx functions to allow for reconfiguring.
944 : : */
945 : : static int
946 : 0 : ionic_dev_stop(struct rte_eth_dev *eth_dev)
947 : : {
948 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
949 : :
950 : 0 : IONIC_PRINT_CALL();
951 : :
952 : 0 : ionic_lif_stop(lif);
953 : :
954 : 0 : return 0;
955 : : }
956 : :
957 : : /*
958 : : * Reset and stop device.
959 : : */
960 : : static int
961 : 0 : ionic_dev_close(struct rte_eth_dev *eth_dev)
962 : : {
963 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
964 : 0 : struct ionic_adapter *adapter = lif->adapter;
965 : :
966 : 0 : IONIC_PRINT_CALL();
967 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
968 : : return 0;
969 : :
970 : 0 : ionic_lif_stop(lif);
971 : :
972 : 0 : ionic_lif_free_queues(lif);
973 : :
974 : 0 : IONIC_PRINT(NOTICE, "Removing device %s", eth_dev->device->name);
975 [ # # ]: 0 : if (adapter->intf->unconfigure_intr)
976 : 0 : (*adapter->intf->unconfigure_intr)(adapter);
977 : :
978 : 0 : rte_eth_dev_destroy(eth_dev, eth_ionic_dev_uninit);
979 : :
980 : 0 : ionic_port_reset(adapter);
981 : 0 : ionic_reset(adapter);
982 [ # # ]: 0 : if (adapter->intf->unmap_bars)
983 : 0 : (*adapter->intf->unmap_bars)(adapter);
984 : :
985 : 0 : rte_free(adapter);
986 : :
987 : 0 : return 0;
988 : : }
989 : :
990 : : int
991 : 0 : eth_ionic_dev_init(struct rte_eth_dev *eth_dev, void *init_params)
992 : : {
993 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
994 : : struct ionic_adapter *adapter = (struct ionic_adapter *)init_params;
995 : : int err;
996 : :
997 : 0 : IONIC_PRINT_CALL();
998 : :
999 : 0 : eth_dev->dev_ops = &ionic_eth_dev_ops;
1000 : 0 : eth_dev->rx_descriptor_status = ionic_dev_rx_descriptor_status;
1001 : 0 : eth_dev->tx_descriptor_status = ionic_dev_tx_descriptor_status;
1002 : :
1003 : : /* Multi-process not supported, primary does initialization anyway */
1004 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
1005 : : return 0;
1006 : :
1007 [ # # ]: 0 : if (adapter->intf->copy_bus_info)
1008 : 0 : (*adapter->intf->copy_bus_info)(adapter, eth_dev);
1009 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
1010 : :
1011 : 0 : lif->eth_dev = eth_dev;
1012 : 0 : lif->adapter = adapter;
1013 : 0 : adapter->lif = lif;
1014 : :
1015 : 0 : IONIC_PRINT(DEBUG, "Up to %u MAC addresses supported",
1016 : : adapter->max_mac_addrs);
1017 : :
1018 : : /* Allocate memory for storing MAC addresses */
1019 : 0 : eth_dev->data->mac_addrs = rte_calloc("ionic",
1020 : 0 : adapter->max_mac_addrs,
1021 : : RTE_ETHER_ADDR_LEN,
1022 : : RTE_CACHE_LINE_SIZE);
1023 [ # # ]: 0 : if (eth_dev->data->mac_addrs == NULL) {
1024 : 0 : IONIC_PRINT(ERR, "Failed to allocate %u bytes needed to "
1025 : : "store MAC addresses",
1026 : : RTE_ETHER_ADDR_LEN * adapter->max_mac_addrs);
1027 : : err = -ENOMEM;
1028 : 0 : goto err;
1029 : : }
1030 : :
1031 : 0 : err = ionic_lif_alloc(lif);
1032 [ # # ]: 0 : if (err) {
1033 : 0 : IONIC_PRINT(ERR, "Cannot allocate LIFs: %d, aborting",
1034 : : err);
1035 : 0 : goto err;
1036 : : }
1037 : :
1038 : 0 : err = ionic_lif_init(lif);
1039 [ # # ]: 0 : if (err) {
1040 : 0 : IONIC_PRINT(ERR, "Cannot init LIFs: %d, aborting", err);
1041 : 0 : goto err_free_lif;
1042 : : }
1043 : :
1044 : : /* Copy the MAC address */
1045 : 0 : rte_ether_addr_copy((struct rte_ether_addr *)lif->mac_addr,
1046 : 0 : ð_dev->data->mac_addrs[0]);
1047 : :
1048 : 0 : IONIC_PRINT(DEBUG, "Port %u initialized", eth_dev->data->port_id);
1049 : :
1050 : 0 : return 0;
1051 : :
1052 : : err_free_lif:
1053 : 0 : ionic_lif_free(lif);
1054 : : err:
1055 : : return err;
1056 : : }
1057 : :
1058 : : static int
1059 : 0 : eth_ionic_dev_uninit(struct rte_eth_dev *eth_dev)
1060 : : {
1061 : 0 : struct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);
1062 : 0 : struct ionic_adapter *adapter = lif->adapter;
1063 : :
1064 : 0 : IONIC_PRINT_CALL();
1065 : :
1066 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
1067 : : return 0;
1068 : :
1069 : 0 : adapter->lif = NULL;
1070 : :
1071 : 0 : ionic_lif_deinit(lif);
1072 : 0 : ionic_lif_free(lif);
1073 : :
1074 [ # # ]: 0 : if (!(lif->state & IONIC_LIF_F_FW_RESET))
1075 : 0 : ionic_lif_reset(lif);
1076 : :
1077 : : return 0;
1078 : : }
1079 : :
1080 : : int
1081 : 0 : eth_ionic_dev_probe(void *bus_dev, struct rte_device *rte_dev,
1082 : : struct ionic_bars *bars, const struct ionic_dev_intf *intf,
1083 : : uint16_t device_id, uint16_t vendor_id)
1084 : : {
1085 : : char name[RTE_ETH_NAME_MAX_LEN];
1086 : : struct ionic_adapter *adapter;
1087 : : struct ionic_hw *hw;
1088 : : unsigned long i;
1089 : : int err;
1090 : :
1091 : : /* Check structs (trigger error at compilation time) */
1092 : : ionic_struct_size_checks();
1093 : :
1094 : : /* Multi-process not supported */
1095 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
1096 : : err = -EPERM;
1097 : 0 : goto err;
1098 : : }
1099 : :
1100 : 0 : adapter = rte_zmalloc("ionic", sizeof(*adapter), RTE_CACHE_LINE_SIZE);
1101 [ # # ]: 0 : if (!adapter) {
1102 : 0 : IONIC_PRINT(ERR, "OOM");
1103 : : err = -ENOMEM;
1104 : 0 : goto err;
1105 : : }
1106 : :
1107 : 0 : adapter->bus_dev = bus_dev;
1108 : 0 : hw = &adapter->hw;
1109 : :
1110 : : /* Vendor and Device ID need to be set before init of shared code */
1111 : 0 : hw->device_id = device_id;
1112 : 0 : hw->vendor_id = vendor_id;
1113 : :
1114 : 0 : err = ionic_init_mac(hw);
1115 [ # # ]: 0 : if (err != 0) {
1116 : 0 : IONIC_PRINT(ERR, "Mac init failed: %d", err);
1117 : : err = -EIO;
1118 : 0 : goto err_free_adapter;
1119 : : }
1120 : :
1121 : 0 : adapter->bars.num_bars = bars->num_bars;
1122 [ # # ]: 0 : for (i = 0; i < bars->num_bars; i++) {
1123 : 0 : adapter->bars.bar[i].vaddr = bars->bar[i].vaddr;
1124 : 0 : adapter->bars.bar[i].bus_addr = bars->bar[i].bus_addr;
1125 : 0 : adapter->bars.bar[i].len = bars->bar[i].len;
1126 : : }
1127 : :
1128 [ # # ]: 0 : if (intf->setup == NULL) {
1129 : 0 : IONIC_PRINT(ERR, "Device setup function is mandatory");
1130 : 0 : goto err_free_adapter;
1131 : : }
1132 : :
1133 : 0 : adapter->intf = intf;
1134 : :
1135 : : /* Parse device arguments */
1136 [ # # ]: 0 : if (adapter->intf->devargs) {
1137 : 0 : err = (*adapter->intf->devargs)(adapter, rte_dev->devargs);
1138 [ # # ]: 0 : if (err) {
1139 : 0 : IONIC_PRINT(ERR, "Cannot parse device arguments");
1140 : 0 : goto err_free_adapter;
1141 : : }
1142 : : }
1143 : :
1144 : : /* Discover ionic dev resources */
1145 : 0 : err = ionic_setup(adapter);
1146 [ # # ]: 0 : if (err) {
1147 : 0 : IONIC_PRINT(ERR, "Cannot setup device: %d, aborting", err);
1148 : 0 : goto err_free_adapter;
1149 : : }
1150 : :
1151 : 0 : err = ionic_identify(adapter);
1152 [ # # ]: 0 : if (err) {
1153 : 0 : IONIC_PRINT(ERR, "Cannot identify device: %d, aborting",
1154 : : err);
1155 : 0 : goto err_free_adapter;
1156 : : }
1157 : :
1158 : 0 : err = ionic_init(adapter);
1159 [ # # ]: 0 : if (err) {
1160 : 0 : IONIC_PRINT(ERR, "Cannot init device: %d, aborting", err);
1161 : 0 : goto err_free_adapter;
1162 : : }
1163 : :
1164 : : /* Configure the ports */
1165 : 0 : err = ionic_port_identify(adapter);
1166 [ # # ]: 0 : if (err) {
1167 : 0 : IONIC_PRINT(ERR, "Cannot identify port: %d, aborting",
1168 : : err);
1169 : 0 : goto err_free_adapter;
1170 : : }
1171 : :
1172 : 0 : err = ionic_port_init(adapter);
1173 [ # # ]: 0 : if (err) {
1174 : 0 : IONIC_PRINT(ERR, "Cannot init port: %d, aborting", err);
1175 : 0 : goto err_free_adapter;
1176 : : }
1177 : :
1178 : : /* Configure LIFs */
1179 : 0 : err = ionic_lif_identify(adapter);
1180 [ # # ]: 0 : if (err) {
1181 : 0 : IONIC_PRINT(ERR, "Cannot identify lif: %d, aborting", err);
1182 : 0 : goto err_free_adapter;
1183 : : }
1184 : :
1185 : : /* Allocate and init LIFs */
1186 : 0 : err = ionic_lifs_size(adapter);
1187 [ # # ]: 0 : if (err) {
1188 : 0 : IONIC_PRINT(ERR, "Cannot size LIFs: %d, aborting", err);
1189 : 0 : goto err_free_adapter;
1190 : : }
1191 : :
1192 : 0 : adapter->max_mac_addrs =
1193 : 0 : rte_le_to_cpu_32(adapter->ident.lif.eth.max_ucast_filters);
1194 : :
1195 [ # # ]: 0 : if (rte_le_to_cpu_32(adapter->ident.dev.nlifs) != 1) {
1196 : 0 : IONIC_PRINT(ERR, "Unexpected request for %d LIFs",
1197 : : rte_le_to_cpu_32(adapter->ident.dev.nlifs));
1198 : 0 : goto err_free_adapter;
1199 : : }
1200 : :
1201 : 0 : snprintf(name, sizeof(name), "%s_lif", rte_dev->name);
1202 : 0 : err = rte_eth_dev_create(rte_dev, name, sizeof(struct ionic_lif),
1203 : : NULL, NULL, eth_ionic_dev_init, adapter);
1204 [ # # ]: 0 : if (err) {
1205 : 0 : IONIC_PRINT(ERR, "Cannot create eth device for %s", name);
1206 : 0 : goto err_free_adapter;
1207 : : }
1208 : :
1209 [ # # ]: 0 : if (adapter->intf->configure_intr) {
1210 : 0 : err = (*adapter->intf->configure_intr)(adapter);
1211 [ # # ]: 0 : if (err) {
1212 : 0 : IONIC_PRINT(ERR, "Failed to configure interrupts");
1213 : 0 : goto err_free_adapter;
1214 : : }
1215 : : }
1216 : :
1217 : : return 0;
1218 : :
1219 : 0 : err_free_adapter:
1220 : 0 : rte_free(adapter);
1221 : : err:
1222 : : return err;
1223 : : }
1224 : :
1225 : : int
1226 : 0 : eth_ionic_dev_remove(struct rte_device *rte_dev)
1227 : : {
1228 : : char name[RTE_ETH_NAME_MAX_LEN];
1229 : : struct rte_eth_dev *eth_dev;
1230 : :
1231 : : /* Adapter lookup is using the eth_dev name */
1232 : 0 : snprintf(name, sizeof(name), "%s_lif", rte_dev->name);
1233 : :
1234 : 0 : eth_dev = rte_eth_dev_allocated(name);
1235 [ # # ]: 0 : if (eth_dev)
1236 : 0 : ionic_dev_close(eth_dev);
1237 : : else
1238 : 0 : IONIC_PRINT(DEBUG, "Cannot find device %s", rte_dev->name);
1239 : :
1240 : 0 : return 0;
1241 : : }
1242 : :
1243 [ - + ]: 235 : RTE_LOG_REGISTER_DEFAULT(ionic_logtype, NOTICE);
|