Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : :
5 : : #include <rte_atomic.h>
6 : : #include <rte_eal.h>
7 : : #include <rte_ether.h>
8 : : #include <rte_malloc.h>
9 : : #include <rte_memzone.h>
10 : : #include <rte_dev.h>
11 : : #include <errno.h>
12 : : #include <rte_alarm.h>
13 : :
14 : : #include "idpf_ethdev.h"
15 : : #include "idpf_rxtx.h"
16 : : #include "../common/tx.h"
17 : :
18 : : #define IDPF_TX_SINGLE_Q "tx_single"
19 : : #define IDPF_RX_SINGLE_Q "rx_single"
20 : : #define IDPF_VPORT "vport"
21 : :
22 : : rte_spinlock_t idpf_adapter_lock;
23 : : /* A list for all adapters, one adapter matches one PCI device */
24 : : struct idpf_adapter_list idpf_adapter_list;
25 : : bool idpf_adapter_list_init;
26 : :
27 : : static const char * const idpf_valid_args[] = {
28 : : IDPF_TX_SINGLE_Q,
29 : : IDPF_RX_SINGLE_Q,
30 : : IDPF_VPORT,
31 : : NULL
32 : : };
33 : :
34 : : uint32_t idpf_supported_speeds[] = {
35 : : RTE_ETH_SPEED_NUM_NONE,
36 : : RTE_ETH_SPEED_NUM_10M,
37 : : RTE_ETH_SPEED_NUM_100M,
38 : : RTE_ETH_SPEED_NUM_1G,
39 : : RTE_ETH_SPEED_NUM_2_5G,
40 : : RTE_ETH_SPEED_NUM_5G,
41 : : RTE_ETH_SPEED_NUM_10G,
42 : : RTE_ETH_SPEED_NUM_20G,
43 : : RTE_ETH_SPEED_NUM_25G,
44 : : RTE_ETH_SPEED_NUM_40G,
45 : : RTE_ETH_SPEED_NUM_50G,
46 : : RTE_ETH_SPEED_NUM_56G,
47 : : RTE_ETH_SPEED_NUM_100G,
48 : : RTE_ETH_SPEED_NUM_200G
49 : : };
50 : :
51 : : static const uint64_t idpf_map_hena_rss[] = {
52 : : [IDPF_HASH_NONF_UNICAST_IPV4_UDP] =
53 : : RTE_ETH_RSS_NONFRAG_IPV4_UDP,
54 : : [IDPF_HASH_NONF_MULTICAST_IPV4_UDP] =
55 : : RTE_ETH_RSS_NONFRAG_IPV4_UDP,
56 : : [IDPF_HASH_NONF_IPV4_UDP] =
57 : : RTE_ETH_RSS_NONFRAG_IPV4_UDP,
58 : : [IDPF_HASH_NONF_IPV4_TCP_SYN_NO_ACK] =
59 : : RTE_ETH_RSS_NONFRAG_IPV4_TCP,
60 : : [IDPF_HASH_NONF_IPV4_TCP] =
61 : : RTE_ETH_RSS_NONFRAG_IPV4_TCP,
62 : : [IDPF_HASH_NONF_IPV4_SCTP] =
63 : : RTE_ETH_RSS_NONFRAG_IPV4_SCTP,
64 : : [IDPF_HASH_NONF_IPV4_OTHER] =
65 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
66 : : [IDPF_HASH_FRAG_IPV4] = RTE_ETH_RSS_FRAG_IPV4,
67 : :
68 : : /* IPv6 */
69 : : [IDPF_HASH_NONF_UNICAST_IPV6_UDP] =
70 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP,
71 : : [IDPF_HASH_NONF_MULTICAST_IPV6_UDP] =
72 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP,
73 : : [IDPF_HASH_NONF_IPV6_UDP] =
74 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP,
75 : : [IDPF_HASH_NONF_IPV6_TCP_SYN_NO_ACK] =
76 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP,
77 : : [IDPF_HASH_NONF_IPV6_TCP] =
78 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP,
79 : : [IDPF_HASH_NONF_IPV6_SCTP] =
80 : : RTE_ETH_RSS_NONFRAG_IPV6_SCTP,
81 : : [IDPF_HASH_NONF_IPV6_OTHER] =
82 : : RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
83 : : [IDPF_HASH_FRAG_IPV6] = RTE_ETH_RSS_FRAG_IPV6,
84 : :
85 : : /* L2 Payload */
86 : : [IDPF_HASH_L2_PAYLOAD] = RTE_ETH_RSS_L2_PAYLOAD
87 : : };
88 : :
89 : : static const uint64_t idpf_ipv4_rss = RTE_ETH_RSS_NONFRAG_IPV4_UDP |
90 : : RTE_ETH_RSS_NONFRAG_IPV4_TCP |
91 : : RTE_ETH_RSS_NONFRAG_IPV4_SCTP |
92 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
93 : : RTE_ETH_RSS_FRAG_IPV4;
94 : :
95 : : static const uint64_t idpf_ipv6_rss = RTE_ETH_RSS_NONFRAG_IPV6_UDP |
96 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP |
97 : : RTE_ETH_RSS_NONFRAG_IPV6_SCTP |
98 : : RTE_ETH_RSS_NONFRAG_IPV6_OTHER |
99 : : RTE_ETH_RSS_FRAG_IPV6;
100 : :
101 : : struct rte_idpf_xstats_name_off {
102 : : char name[RTE_ETH_XSTATS_NAME_SIZE];
103 : : unsigned int offset;
104 : : };
105 : :
106 : : static const struct rte_idpf_xstats_name_off rte_idpf_stats_strings[] = {
107 : : {"rx_bytes", offsetof(struct virtchnl2_vport_stats, rx_bytes)},
108 : : {"rx_unicast_packets", offsetof(struct virtchnl2_vport_stats, rx_unicast)},
109 : : {"rx_multicast_packets", offsetof(struct virtchnl2_vport_stats, rx_multicast)},
110 : : {"rx_broadcast_packets", offsetof(struct virtchnl2_vport_stats, rx_broadcast)},
111 : : {"rx_dropped_packets", offsetof(struct virtchnl2_vport_stats, rx_discards)},
112 : : {"rx_errors", offsetof(struct virtchnl2_vport_stats, rx_errors)},
113 : : {"rx_unknown_protocol_packets", offsetof(struct virtchnl2_vport_stats,
114 : : rx_unknown_protocol)},
115 : : {"tx_bytes", offsetof(struct virtchnl2_vport_stats, tx_bytes)},
116 : : {"tx_unicast_packets", offsetof(struct virtchnl2_vport_stats, tx_unicast)},
117 : : {"tx_multicast_packets", offsetof(struct virtchnl2_vport_stats, tx_multicast)},
118 : : {"tx_broadcast_packets", offsetof(struct virtchnl2_vport_stats, tx_broadcast)},
119 : : {"tx_dropped_packets", offsetof(struct virtchnl2_vport_stats, tx_discards)},
120 : : {"tx_error_packets", offsetof(struct virtchnl2_vport_stats, tx_errors)}};
121 : :
122 : : #define IDPF_NB_XSTATS (sizeof(rte_idpf_stats_strings) / \
123 : : sizeof(rte_idpf_stats_strings[0]))
124 : :
125 : : static int
126 : 0 : idpf_dev_link_update(struct rte_eth_dev *dev,
127 : : __rte_unused int wait_to_complete)
128 : : {
129 [ # # ]: 0 : struct idpf_vport *vport = dev->data->dev_private;
130 : : struct rte_eth_link new_link;
131 : : unsigned int i;
132 : :
133 : : memset(&new_link, 0, sizeof(new_link));
134 : :
135 : : /* initialize with default value */
136 [ # # ]: 0 : new_link.link_speed = vport->link_up ? RTE_ETH_SPEED_NUM_UNKNOWN : RTE_ETH_SPEED_NUM_NONE;
137 : :
138 : : /* update in case a match */
139 [ # # ]: 0 : for (i = 0; i < RTE_DIM(idpf_supported_speeds); i++) {
140 [ # # ]: 0 : if (vport->link_speed == idpf_supported_speeds[i]) {
141 : 0 : new_link.link_speed = vport->link_speed;
142 : 0 : break;
143 : : }
144 : : }
145 : :
146 : 0 : new_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
147 : 0 : new_link.link_status = vport->link_up ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
148 : 0 : new_link.link_autoneg = (dev->data->dev_conf.link_speeds & RTE_ETH_LINK_SPEED_FIXED) ?
149 [ # # ]: 0 : RTE_ETH_LINK_FIXED : RTE_ETH_LINK_AUTONEG;
150 : :
151 : 0 : return rte_eth_linkstatus_set(dev, &new_link);
152 : : }
153 : :
154 : : static int
155 : 0 : idpf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
156 : : {
157 : 0 : struct idpf_vport *vport = dev->data->dev_private;
158 : 0 : struct idpf_adapter *adapter = vport->adapter;
159 : :
160 : 0 : dev_info->max_rx_queues = adapter->caps.max_rx_q;
161 : 0 : dev_info->max_tx_queues = adapter->caps.max_tx_q;
162 : 0 : dev_info->min_rx_bufsize = IDPF_MIN_BUF_SIZE;
163 : 0 : dev_info->max_rx_pktlen = vport->max_mtu + IDPF_ETH_OVERHEAD;
164 : :
165 : 0 : dev_info->max_mtu = vport->max_mtu;
166 : 0 : dev_info->min_mtu = RTE_ETHER_MIN_MTU;
167 : :
168 : 0 : dev_info->hash_key_size = vport->rss_key_size;
169 : 0 : dev_info->reta_size = vport->rss_lut_size;
170 : :
171 : 0 : dev_info->flow_type_rss_offloads = IDPF_RSS_OFFLOAD_ALL;
172 : :
173 : 0 : dev_info->rx_offload_capa =
174 : : RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
175 : : RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
176 : : RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
177 : : RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
178 : : RTE_ETH_RX_OFFLOAD_TIMESTAMP |
179 : : RTE_ETH_RX_OFFLOAD_SCATTER;
180 : :
181 : 0 : dev_info->tx_offload_capa =
182 : : RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
183 : : RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
184 : : RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
185 : : RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
186 : : RTE_ETH_TX_OFFLOAD_TCP_TSO |
187 : : RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
188 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
189 : :
190 : 0 : dev_info->default_txconf = (struct rte_eth_txconf) {
191 : : .tx_free_thresh = IDPF_DEFAULT_TX_FREE_THRESH,
192 : : .tx_rs_thresh = IDPF_DEFAULT_TX_RS_THRESH,
193 : : };
194 : :
195 : 0 : dev_info->default_rxconf = (struct rte_eth_rxconf) {
196 : : .rx_free_thresh = IDPF_DEFAULT_RX_FREE_THRESH,
197 : : };
198 : :
199 : 0 : dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
200 : : .nb_max = IDPF_MAX_RING_DESC,
201 : : .nb_min = IDPF_MIN_RING_DESC,
202 : : .nb_align = IDPF_ALIGN_RING_DESC,
203 : : };
204 : :
205 : 0 : dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
206 : : .nb_max = IDPF_MAX_RING_DESC,
207 : : .nb_min = IDPF_MIN_RING_DESC,
208 : : .nb_align = IDPF_ALIGN_RING_DESC,
209 : : };
210 : :
211 : 0 : return 0;
212 : : }
213 : :
214 : : static int
215 : 0 : idpf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
216 : : {
217 : 0 : struct idpf_vport *vport = dev->data->dev_private;
218 : :
219 : : /* mtu setting is forbidden if port is start */
220 [ # # ]: 0 : if (dev->data->dev_started) {
221 : 0 : PMD_DRV_LOG(ERR, "port must be stopped before configuration");
222 : 0 : return -EBUSY;
223 : : }
224 : :
225 [ # # ]: 0 : if (mtu > vport->max_mtu) {
226 : 0 : PMD_DRV_LOG(ERR, "MTU should be less than %d", vport->max_mtu);
227 : 0 : return -EINVAL;
228 : : }
229 : :
230 : 0 : vport->max_pkt_len = mtu + IDPF_ETH_OVERHEAD;
231 : :
232 : 0 : return 0;
233 : : }
234 : :
235 : : static const uint32_t *
236 : 0 : idpf_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
237 : : size_t *no_of_elements)
238 : : {
239 : : static const uint32_t ptypes[] = {
240 : : RTE_PTYPE_L2_ETHER,
241 : : RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
242 : : RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
243 : : RTE_PTYPE_L4_FRAG,
244 : : RTE_PTYPE_L4_UDP,
245 : : RTE_PTYPE_L4_TCP,
246 : : RTE_PTYPE_L4_SCTP,
247 : : RTE_PTYPE_L4_ICMP,
248 : : };
249 : :
250 : 0 : *no_of_elements = RTE_DIM(ptypes);
251 : 0 : return ptypes;
252 : : }
253 : :
254 : : static uint64_t
255 : 0 : idpf_get_mbuf_alloc_failed_stats(struct rte_eth_dev *dev)
256 : : {
257 : : uint64_t mbuf_alloc_failed = 0;
258 : : struct idpf_rx_queue *rxq;
259 : : int i = 0;
260 : :
261 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
262 : 0 : rxq = dev->data->rx_queues[i];
263 : 0 : mbuf_alloc_failed += rte_atomic_load_explicit(&rxq->rx_stats.mbuf_alloc_failed,
264 : : rte_memory_order_relaxed);
265 : : }
266 : :
267 : 0 : return mbuf_alloc_failed;
268 : : }
269 : :
270 : : static int
271 : 0 : idpf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
272 : : {
273 : 0 : struct idpf_vport *vport =
274 : 0 : (struct idpf_vport *)dev->data->dev_private;
275 : 0 : struct virtchnl2_vport_stats *pstats = NULL;
276 : : int ret;
277 : :
278 : 0 : ret = idpf_vc_stats_query(vport, &pstats);
279 [ # # ]: 0 : if (ret == 0) {
280 [ # # ]: 0 : uint8_t crc_stats_len = (dev->data->dev_conf.rxmode.offloads &
281 : : RTE_ETH_RX_OFFLOAD_KEEP_CRC) ? 0 :
282 : : RTE_ETHER_CRC_LEN;
283 : :
284 : 0 : idpf_vport_stats_update(&vport->eth_stats_offset, pstats);
285 : 0 : stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
286 : 0 : pstats->rx_broadcast;
287 : 0 : stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
288 : 0 : pstats->tx_unicast;
289 : 0 : stats->ierrors = pstats->rx_errors;
290 : 0 : stats->imissed = pstats->rx_discards;
291 : 0 : stats->oerrors = pstats->tx_errors + pstats->tx_discards;
292 : 0 : stats->ibytes = pstats->rx_bytes;
293 : 0 : stats->ibytes -= stats->ipackets * crc_stats_len;
294 : 0 : stats->obytes = pstats->tx_bytes;
295 : :
296 : 0 : dev->data->rx_mbuf_alloc_failed = idpf_get_mbuf_alloc_failed_stats(dev);
297 : 0 : stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
298 : : } else {
299 : 0 : PMD_DRV_LOG(ERR, "Get statistics failed");
300 : : }
301 : 0 : return ret;
302 : : }
303 : :
304 : : static void
305 : 0 : idpf_reset_mbuf_alloc_failed_stats(struct rte_eth_dev *dev)
306 : : {
307 : : struct idpf_rx_queue *rxq;
308 : : int i;
309 : :
310 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
311 : 0 : rxq = dev->data->rx_queues[i];
312 : 0 : rte_atomic_store_explicit(&rxq->rx_stats.mbuf_alloc_failed, 0,
313 : : rte_memory_order_relaxed);
314 : : }
315 : 0 : }
316 : :
317 : : static int
318 : 0 : idpf_dev_stats_reset(struct rte_eth_dev *dev)
319 : : {
320 : 0 : struct idpf_vport *vport =
321 : 0 : (struct idpf_vport *)dev->data->dev_private;
322 : 0 : struct virtchnl2_vport_stats *pstats = NULL;
323 : : int ret;
324 : :
325 : 0 : ret = idpf_vc_stats_query(vport, &pstats);
326 [ # # ]: 0 : if (ret != 0)
327 : : return ret;
328 : :
329 : : /* set stats offset base on current values */
330 : 0 : vport->eth_stats_offset = *pstats;
331 : :
332 : 0 : idpf_reset_mbuf_alloc_failed_stats(dev);
333 : :
334 : 0 : return 0;
335 : : }
336 : :
337 : 0 : static int idpf_dev_xstats_reset(struct rte_eth_dev *dev)
338 : : {
339 : 0 : idpf_dev_stats_reset(dev);
340 : 0 : return 0;
341 : : }
342 : :
343 : 0 : static int idpf_dev_xstats_get(struct rte_eth_dev *dev,
344 : : struct rte_eth_xstat *xstats, unsigned int n)
345 : : {
346 : 0 : struct idpf_vport *vport =
347 : 0 : (struct idpf_vport *)dev->data->dev_private;
348 : 0 : struct virtchnl2_vport_stats *pstats = NULL;
349 : : unsigned int i;
350 : : int ret;
351 : :
352 [ # # ]: 0 : if (n < IDPF_NB_XSTATS)
353 : : return IDPF_NB_XSTATS;
354 : :
355 [ # # ]: 0 : if (!xstats)
356 : : return 0;
357 : :
358 : 0 : ret = idpf_vc_stats_query(vport, &pstats);
359 [ # # ]: 0 : if (ret) {
360 : 0 : PMD_DRV_LOG(ERR, "Get statistics failed");
361 : 0 : return 0;
362 : : }
363 : :
364 : 0 : idpf_vport_stats_update(&vport->eth_stats_offset, pstats);
365 : :
366 : : /* loop over xstats array and values from pstats */
367 [ # # ]: 0 : for (i = 0; i < IDPF_NB_XSTATS; i++) {
368 : 0 : xstats[i].id = i;
369 : 0 : xstats[i].value = *(uint64_t *)(((char *)pstats) +
370 : 0 : rte_idpf_stats_strings[i].offset);
371 : : }
372 : : return IDPF_NB_XSTATS;
373 : : }
374 : :
375 : 0 : static int idpf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
376 : : struct rte_eth_xstat_name *xstats_names,
377 : : __rte_unused unsigned int limit)
378 : : {
379 : : unsigned int i;
380 : :
381 [ # # ]: 0 : if (xstats_names)
382 [ # # ]: 0 : for (i = 0; i < IDPF_NB_XSTATS; i++) {
383 : 0 : snprintf(xstats_names[i].name,
384 : : sizeof(xstats_names[i].name),
385 : 0 : "%s", rte_idpf_stats_strings[i].name);
386 : : }
387 : 0 : return IDPF_NB_XSTATS;
388 : : }
389 : :
390 : 0 : static int idpf_config_rss_hf(struct idpf_vport *vport, uint64_t rss_hf)
391 : : {
392 : : uint64_t hena = 0;
393 : : uint16_t i;
394 : :
395 : : /**
396 : : * RTE_ETH_RSS_IPV4 and RTE_ETH_RSS_IPV6 can be considered as 2
397 : : * generalizations of all other IPv4 and IPv6 RSS types.
398 : : */
399 [ # # ]: 0 : if (rss_hf & RTE_ETH_RSS_IPV4)
400 : 0 : rss_hf |= idpf_ipv4_rss;
401 : :
402 [ # # ]: 0 : if (rss_hf & RTE_ETH_RSS_IPV6)
403 : 0 : rss_hf |= idpf_ipv6_rss;
404 : :
405 [ # # ]: 0 : for (i = 0; i < RTE_DIM(idpf_map_hena_rss); i++) {
406 [ # # ]: 0 : if (idpf_map_hena_rss[i] & rss_hf)
407 : 0 : hena |= BIT_ULL(i);
408 : : }
409 : :
410 : : /**
411 : : * At present, cp doesn't process the virtual channel msg of rss_hf configuration,
412 : : * tips are given below.
413 : : */
414 [ # # ]: 0 : if (hena != vport->rss_hf)
415 : 0 : PMD_DRV_LOG(WARNING, "Updating RSS Hash Function is not supported at present.");
416 : :
417 : 0 : return 0;
418 : : }
419 : :
420 : : static int
421 : 0 : idpf_init_rss(struct idpf_vport *vport)
422 : : {
423 : : struct rte_eth_rss_conf *rss_conf;
424 : : struct rte_eth_dev_data *dev_data;
425 : : uint16_t i, nb_q;
426 : : int ret = 0;
427 : :
428 : 0 : dev_data = vport->dev_data;
429 : : rss_conf = &dev_data->dev_conf.rx_adv_conf.rss_conf;
430 : 0 : nb_q = dev_data->nb_rx_queues;
431 : :
432 [ # # ]: 0 : if (rss_conf->rss_key == NULL) {
433 [ # # ]: 0 : for (i = 0; i < vport->rss_key_size; i++)
434 : 0 : vport->rss_key[i] = (uint8_t)rte_rand();
435 [ # # ]: 0 : } else if (rss_conf->rss_key_len != vport->rss_key_size) {
436 : 0 : PMD_INIT_LOG(ERR, "Invalid RSS key length in RSS configuration, should be %d",
437 : : vport->rss_key_size);
438 : 0 : return -EINVAL;
439 : : } else {
440 [ # # ]: 0 : rte_memcpy(vport->rss_key, rss_conf->rss_key,
441 : : vport->rss_key_size);
442 : : }
443 : :
444 [ # # ]: 0 : for (i = 0; i < vport->rss_lut_size; i++)
445 : 0 : vport->rss_lut[i] = i % nb_q;
446 : :
447 : 0 : vport->rss_hf = IDPF_DEFAULT_RSS_HASH_EXPANDED;
448 : :
449 : 0 : ret = idpf_vport_rss_config(vport);
450 [ # # ]: 0 : if (ret != 0)
451 : 0 : PMD_INIT_LOG(ERR, "Failed to configure RSS");
452 : :
453 : : return ret;
454 : : }
455 : :
456 : : static int
457 : 0 : idpf_rss_reta_update(struct rte_eth_dev *dev,
458 : : struct rte_eth_rss_reta_entry64 *reta_conf,
459 : : uint16_t reta_size)
460 : : {
461 : 0 : struct idpf_vport *vport = dev->data->dev_private;
462 : 0 : struct idpf_adapter *adapter = vport->adapter;
463 : : uint16_t idx, shift;
464 : : int ret = 0;
465 : : uint16_t i;
466 : :
467 [ # # # # ]: 0 : if (adapter->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
468 : 0 : PMD_DRV_LOG(DEBUG, "RSS is not supported");
469 : 0 : return -ENOTSUP;
470 : : }
471 : :
472 [ # # ]: 0 : if (reta_size != vport->rss_lut_size) {
473 : 0 : PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
474 : : "(%d) doesn't match the number of hardware can "
475 : : "support (%d)",
476 : : reta_size, vport->rss_lut_size);
477 : 0 : return -EINVAL;
478 : : }
479 : :
480 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
481 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
482 : 0 : shift = i % RTE_ETH_RETA_GROUP_SIZE;
483 [ # # ]: 0 : if (reta_conf[idx].mask & (1ULL << shift))
484 : 0 : vport->rss_lut[i] = reta_conf[idx].reta[shift];
485 : : }
486 : :
487 : : /* send virtchnl ops to configure RSS */
488 : 0 : ret = idpf_vc_rss_lut_set(vport);
489 [ # # ]: 0 : if (ret)
490 : 0 : PMD_INIT_LOG(ERR, "Failed to configure RSS lut");
491 : :
492 : : return ret;
493 : : }
494 : :
495 : : static int
496 : 0 : idpf_rss_reta_query(struct rte_eth_dev *dev,
497 : : struct rte_eth_rss_reta_entry64 *reta_conf,
498 : : uint16_t reta_size)
499 : : {
500 : 0 : struct idpf_vport *vport = dev->data->dev_private;
501 : 0 : struct idpf_adapter *adapter = vport->adapter;
502 : : uint16_t idx, shift;
503 : : int ret = 0;
504 : : uint16_t i;
505 : :
506 [ # # # # ]: 0 : if (adapter->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
507 : 0 : PMD_DRV_LOG(DEBUG, "RSS is not supported");
508 : 0 : return -ENOTSUP;
509 : : }
510 : :
511 [ # # ]: 0 : if (reta_size != vport->rss_lut_size) {
512 : 0 : PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
513 : : "(%d) doesn't match the number of hardware can "
514 : : "support (%d)", reta_size, vport->rss_lut_size);
515 : 0 : return -EINVAL;
516 : : }
517 : :
518 : 0 : ret = idpf_vc_rss_lut_get(vport);
519 [ # # ]: 0 : if (ret) {
520 : 0 : PMD_DRV_LOG(ERR, "Failed to get RSS LUT");
521 : 0 : return ret;
522 : : }
523 : :
524 [ # # ]: 0 : for (i = 0; i < reta_size; i++) {
525 : 0 : idx = i / RTE_ETH_RETA_GROUP_SIZE;
526 : 0 : shift = i % RTE_ETH_RETA_GROUP_SIZE;
527 [ # # ]: 0 : if (reta_conf[idx].mask & (1ULL << shift))
528 : 0 : reta_conf[idx].reta[shift] = vport->rss_lut[i];
529 : : }
530 : :
531 : : return 0;
532 : : }
533 : :
534 : : static int
535 : 0 : idpf_rss_hash_update(struct rte_eth_dev *dev,
536 : : struct rte_eth_rss_conf *rss_conf)
537 : : {
538 : 0 : struct idpf_vport *vport = dev->data->dev_private;
539 : 0 : struct idpf_adapter *adapter = vport->adapter;
540 : : int ret = 0;
541 : :
542 [ # # # # ]: 0 : if (adapter->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
543 : 0 : PMD_DRV_LOG(DEBUG, "RSS is not supported");
544 : 0 : return -ENOTSUP;
545 : : }
546 : :
547 [ # # # # ]: 0 : if (!rss_conf->rss_key || rss_conf->rss_key_len == 0) {
548 : 0 : PMD_DRV_LOG(DEBUG, "No key to be configured");
549 : 0 : goto skip_rss_key;
550 [ # # ]: 0 : } else if (rss_conf->rss_key_len != vport->rss_key_size) {
551 : 0 : PMD_DRV_LOG(ERR, "The size of hash key configured "
552 : : "(%d) doesn't match the size of hardware can "
553 : : "support (%d)",
554 : : rss_conf->rss_key_len,
555 : : vport->rss_key_size);
556 : 0 : return -EINVAL;
557 : : }
558 : :
559 [ # # ]: 0 : rte_memcpy(vport->rss_key, rss_conf->rss_key,
560 : : vport->rss_key_size);
561 : 0 : ret = idpf_vc_rss_key_set(vport);
562 [ # # ]: 0 : if (ret != 0) {
563 : 0 : PMD_INIT_LOG(ERR, "Failed to configure RSS key");
564 : 0 : return ret;
565 : : }
566 : :
567 : 0 : skip_rss_key:
568 : 0 : ret = idpf_config_rss_hf(vport, rss_conf->rss_hf);
569 [ # # ]: 0 : if (ret != 0) {
570 : 0 : PMD_INIT_LOG(ERR, "Failed to configure RSS hash");
571 : 0 : return ret;
572 : : }
573 : :
574 : : return 0;
575 : : }
576 : :
577 : : static uint64_t
578 : 0 : idpf_map_general_rss_hf(uint64_t config_rss_hf, uint64_t last_general_rss_hf)
579 : : {
580 : : uint64_t valid_rss_hf = 0;
581 : : uint16_t i;
582 : :
583 [ # # ]: 0 : for (i = 0; i < RTE_DIM(idpf_map_hena_rss); i++) {
584 : 0 : uint64_t bit = BIT_ULL(i);
585 : :
586 [ # # ]: 0 : if (bit & config_rss_hf)
587 : 0 : valid_rss_hf |= idpf_map_hena_rss[i];
588 : : }
589 : :
590 [ # # ]: 0 : if (valid_rss_hf & idpf_ipv4_rss)
591 : 0 : valid_rss_hf |= last_general_rss_hf & RTE_ETH_RSS_IPV4;
592 : :
593 [ # # ]: 0 : if (valid_rss_hf & idpf_ipv6_rss)
594 : 0 : valid_rss_hf |= last_general_rss_hf & RTE_ETH_RSS_IPV6;
595 : :
596 : 0 : return valid_rss_hf;
597 : : }
598 : :
599 : : static int
600 : 0 : idpf_rss_hash_conf_get(struct rte_eth_dev *dev,
601 : : struct rte_eth_rss_conf *rss_conf)
602 : : {
603 : 0 : struct idpf_vport *vport = dev->data->dev_private;
604 : 0 : struct idpf_adapter *adapter = vport->adapter;
605 : : int ret = 0;
606 : :
607 [ # # # # ]: 0 : if (adapter->caps.rss_caps == 0 || dev->data->nb_rx_queues == 0) {
608 : 0 : PMD_DRV_LOG(DEBUG, "RSS is not supported");
609 : 0 : return -ENOTSUP;
610 : : }
611 : :
612 : 0 : ret = idpf_vc_rss_hash_get(vport);
613 [ # # ]: 0 : if (ret) {
614 : 0 : PMD_DRV_LOG(ERR, "Failed to get RSS hf");
615 : 0 : return ret;
616 : : }
617 : :
618 : 0 : rss_conf->rss_hf = idpf_map_general_rss_hf(vport->rss_hf, vport->last_general_rss_hf);
619 : :
620 [ # # ]: 0 : if (!rss_conf->rss_key)
621 : : return 0;
622 : :
623 : 0 : ret = idpf_vc_rss_key_get(vport);
624 [ # # ]: 0 : if (ret) {
625 : 0 : PMD_DRV_LOG(ERR, "Failed to get RSS key");
626 : 0 : return ret;
627 : : }
628 : :
629 [ # # ]: 0 : if (rss_conf->rss_key_len > vport->rss_key_size)
630 : 0 : rss_conf->rss_key_len = vport->rss_key_size;
631 : :
632 [ # # ]: 0 : rte_memcpy(rss_conf->rss_key, vport->rss_key, rss_conf->rss_key_len);
633 : :
634 : : return 0;
635 : : }
636 : :
637 : : static int
638 : 0 : idpf_dev_configure(struct rte_eth_dev *dev)
639 : : {
640 : 0 : struct idpf_vport *vport = dev->data->dev_private;
641 : : struct rte_eth_conf *conf = &dev->data->dev_conf;
642 : 0 : struct idpf_adapter *adapter = vport->adapter;
643 : : int ret;
644 : :
645 [ # # ]: 0 : if (conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) {
646 : 0 : PMD_INIT_LOG(ERR, "Setting link speed is not supported");
647 : 0 : return -ENOTSUP;
648 : : }
649 : :
650 [ # # ]: 0 : if (conf->txmode.mq_mode != RTE_ETH_MQ_TX_NONE) {
651 : 0 : PMD_INIT_LOG(ERR, "Multi-queue TX mode %d is not supported",
652 : : conf->txmode.mq_mode);
653 : 0 : return -ENOTSUP;
654 : : }
655 : :
656 [ # # ]: 0 : if (conf->lpbk_mode != 0) {
657 : 0 : PMD_INIT_LOG(ERR, "Loopback operation mode %d is not supported",
658 : : conf->lpbk_mode);
659 : 0 : return -ENOTSUP;
660 : : }
661 : :
662 [ # # ]: 0 : if (conf->dcb_capability_en != 0) {
663 : 0 : PMD_INIT_LOG(ERR, "Priority Flow Control(PFC) if not supported");
664 : 0 : return -ENOTSUP;
665 : : }
666 : :
667 [ # # ]: 0 : if (conf->intr_conf.lsc != 0) {
668 : 0 : PMD_INIT_LOG(ERR, "LSC interrupt is not supported");
669 : 0 : return -ENOTSUP;
670 : : }
671 : :
672 [ # # ]: 0 : if (conf->intr_conf.rxq != 0) {
673 : 0 : PMD_INIT_LOG(ERR, "RXQ interrupt is not supported");
674 : 0 : return -ENOTSUP;
675 : : }
676 : :
677 [ # # ]: 0 : if (conf->intr_conf.rmv != 0) {
678 : 0 : PMD_INIT_LOG(ERR, "RMV interrupt is not supported");
679 : 0 : return -ENOTSUP;
680 : : }
681 : :
682 [ # # # # ]: 0 : if (adapter->caps.rss_caps != 0 && dev->data->nb_rx_queues != 0) {
683 : 0 : ret = idpf_init_rss(vport);
684 [ # # ]: 0 : if (ret != 0) {
685 : 0 : PMD_INIT_LOG(ERR, "Failed to init rss");
686 : 0 : return ret;
687 : : }
688 : : } else {
689 : 0 : PMD_INIT_LOG(ERR, "RSS is not supported.");
690 : 0 : return -1;
691 : : }
692 : :
693 : 0 : vport->max_pkt_len =
694 [ # # ]: 0 : (dev->data->mtu == 0) ? IDPF_DEFAULT_MTU : dev->data->mtu +
695 : : IDPF_ETH_OVERHEAD;
696 : :
697 : 0 : return 0;
698 : : }
699 : :
700 : : static int
701 : : idpf_config_rx_queues_irqs(struct rte_eth_dev *dev)
702 : : {
703 : 0 : struct idpf_vport *vport = dev->data->dev_private;
704 : 0 : uint16_t nb_rx_queues = dev->data->nb_rx_queues;
705 : :
706 : 0 : return idpf_vport_irq_map_config(vport, nb_rx_queues);
707 : : }
708 : :
709 : : static int
710 : 0 : idpf_start_queues(struct rte_eth_dev *dev)
711 : : {
712 : : struct idpf_rx_queue *rxq;
713 : : struct ci_tx_queue *txq;
714 : : int err = 0;
715 : : int i;
716 : :
717 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
718 : 0 : txq = dev->data->tx_queues[i];
719 [ # # # # ]: 0 : if (txq == NULL || txq->tx_deferred_start)
720 : 0 : continue;
721 : 0 : err = idpf_tx_queue_start(dev, i);
722 [ # # ]: 0 : if (err != 0) {
723 : 0 : PMD_DRV_LOG(ERR, "Fail to start Tx queue %u", i);
724 : 0 : return err;
725 : : }
726 : : }
727 : :
728 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
729 : 0 : rxq = dev->data->rx_queues[i];
730 [ # # # # ]: 0 : if (rxq == NULL || rxq->rx_deferred_start)
731 : 0 : continue;
732 : 0 : err = idpf_rx_queue_start(dev, i);
733 [ # # ]: 0 : if (err != 0) {
734 : 0 : PMD_DRV_LOG(ERR, "Fail to start Rx queue %u", i);
735 : 0 : return err;
736 : : }
737 : : }
738 : :
739 : : return err;
740 : : }
741 : :
742 : : static int
743 : 0 : idpf_dev_start(struct rte_eth_dev *dev)
744 : : {
745 : 0 : struct idpf_vport *vport = dev->data->dev_private;
746 : 0 : struct idpf_adapter *base = vport->adapter;
747 : 0 : struct idpf_adapter_ext *adapter = IDPF_ADAPTER_TO_EXT(base);
748 : 0 : uint16_t num_allocated_vectors = base->caps.num_allocated_vectors;
749 : : uint16_t req_vecs_num;
750 : : int ret;
751 : :
752 : : req_vecs_num = IDPF_DFLT_Q_VEC_NUM;
753 [ # # ]: 0 : if (req_vecs_num + adapter->used_vecs_num > num_allocated_vectors) {
754 : 0 : PMD_DRV_LOG(ERR, "The accumulated request vectors' number should be less than %d",
755 : : num_allocated_vectors);
756 : : ret = -EINVAL;
757 : 0 : goto err_vec;
758 : : }
759 : :
760 : 0 : ret = idpf_vc_vectors_alloc(vport, req_vecs_num);
761 [ # # ]: 0 : if (ret != 0) {
762 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate interrupt vectors");
763 : 0 : goto err_vec;
764 : : }
765 : 0 : adapter->used_vecs_num += req_vecs_num;
766 : :
767 : : ret = idpf_config_rx_queues_irqs(dev);
768 [ # # ]: 0 : if (ret != 0) {
769 : 0 : PMD_DRV_LOG(ERR, "Failed to configure irqs");
770 : 0 : goto err_irq;
771 : : }
772 : :
773 : 0 : ret = idpf_start_queues(dev);
774 [ # # ]: 0 : if (ret != 0) {
775 : 0 : PMD_DRV_LOG(ERR, "Failed to start queues");
776 : 0 : goto err_startq;
777 : : }
778 : :
779 : 0 : idpf_set_rx_function(dev);
780 : 0 : idpf_set_tx_function(dev);
781 : :
782 : 0 : ret = idpf_vc_vport_ena_dis(vport, true);
783 [ # # ]: 0 : if (ret != 0) {
784 : 0 : PMD_DRV_LOG(ERR, "Failed to enable vport");
785 : 0 : goto err_vport;
786 : : }
787 : :
788 [ # # ]: 0 : if (idpf_dev_stats_reset(dev))
789 : 0 : PMD_DRV_LOG(ERR, "Failed to reset stats");
790 : :
791 : : return 0;
792 : :
793 : : err_vport:
794 : 0 : idpf_stop_queues(dev);
795 : 0 : err_startq:
796 : 0 : idpf_vport_irq_unmap_config(vport, dev->data->nb_rx_queues);
797 : 0 : err_irq:
798 : 0 : idpf_vc_vectors_dealloc(vport);
799 : : err_vec:
800 : : return ret;
801 : : }
802 : :
803 : : static int
804 : 0 : idpf_dev_stop(struct rte_eth_dev *dev)
805 : : {
806 : 0 : struct idpf_vport *vport = dev->data->dev_private;
807 : :
808 [ # # ]: 0 : if (dev->data->dev_started == 0)
809 : : return 0;
810 : :
811 : 0 : idpf_vc_vport_ena_dis(vport, false);
812 : :
813 : 0 : idpf_stop_queues(dev);
814 : :
815 : 0 : idpf_vport_irq_unmap_config(vport, dev->data->nb_rx_queues);
816 : :
817 : 0 : idpf_vc_vectors_dealloc(vport);
818 : :
819 : 0 : return 0;
820 : : }
821 : :
822 : : static int
823 : 0 : idpf_dev_close(struct rte_eth_dev *dev)
824 : : {
825 : 0 : struct idpf_vport *vport = dev->data->dev_private;
826 : 0 : struct idpf_adapter_ext *adapter = IDPF_ADAPTER_TO_EXT(vport->adapter);
827 : :
828 : 0 : idpf_dev_stop(dev);
829 : :
830 : 0 : idpf_vport_deinit(vport);
831 : :
832 : 0 : adapter->cur_vports &= ~RTE_BIT32(vport->devarg_id);
833 : 0 : adapter->cur_vport_nb--;
834 : 0 : dev->data->dev_private = NULL;
835 : 0 : adapter->vports[vport->sw_idx] = NULL;
836 : 0 : rte_free(vport);
837 : :
838 : 0 : return 0;
839 : : }
840 : :
841 : : static const struct eth_dev_ops idpf_eth_dev_ops = {
842 : : .dev_configure = idpf_dev_configure,
843 : : .dev_close = idpf_dev_close,
844 : : .rx_queue_setup = idpf_rx_queue_setup,
845 : : .tx_queue_setup = idpf_tx_queue_setup,
846 : : .dev_infos_get = idpf_dev_info_get,
847 : : .dev_start = idpf_dev_start,
848 : : .dev_stop = idpf_dev_stop,
849 : : .link_update = idpf_dev_link_update,
850 : : .rx_queue_start = idpf_rx_queue_start,
851 : : .tx_queue_start = idpf_tx_queue_start,
852 : : .rx_queue_stop = idpf_rx_queue_stop,
853 : : .tx_queue_stop = idpf_tx_queue_stop,
854 : : .rx_queue_release = idpf_dev_rx_queue_release,
855 : : .tx_queue_release = idpf_dev_tx_queue_release,
856 : : .mtu_set = idpf_dev_mtu_set,
857 : : .dev_supported_ptypes_get = idpf_dev_supported_ptypes_get,
858 : : .stats_get = idpf_dev_stats_get,
859 : : .stats_reset = idpf_dev_stats_reset,
860 : : .reta_update = idpf_rss_reta_update,
861 : : .reta_query = idpf_rss_reta_query,
862 : : .rss_hash_update = idpf_rss_hash_update,
863 : : .rss_hash_conf_get = idpf_rss_hash_conf_get,
864 : : .xstats_get = idpf_dev_xstats_get,
865 : : .xstats_get_names = idpf_dev_xstats_get_names,
866 : : .xstats_reset = idpf_dev_xstats_reset,
867 : : };
868 : :
869 : : static int
870 : 0 : insert_value(struct idpf_devargs *devargs, uint16_t id)
871 : : {
872 : : uint16_t i;
873 : :
874 : : /* ignore duplicate */
875 [ # # ]: 0 : for (i = 0; i < devargs->req_vport_nb; i++) {
876 [ # # ]: 0 : if (devargs->req_vports[i] == id)
877 : : return 0;
878 : : }
879 : :
880 [ # # ]: 0 : if (devargs->req_vport_nb >= RTE_DIM(devargs->req_vports)) {
881 : 0 : PMD_INIT_LOG(ERR, "Total vport number can't be > %d",
882 : : IDPF_MAX_VPORT_NUM);
883 : 0 : return -EINVAL;
884 : : }
885 : :
886 : 0 : devargs->req_vports[devargs->req_vport_nb] = id;
887 : 0 : devargs->req_vport_nb++;
888 : :
889 : 0 : return 0;
890 : : }
891 : :
892 : : static const char *
893 : 0 : parse_range(const char *value, struct idpf_devargs *devargs)
894 : : {
895 : : uint16_t lo, hi, i;
896 : 0 : int n = 0;
897 : : int result;
898 : : const char *pos = value;
899 : :
900 : 0 : result = sscanf(value, "%hu%n-%hu%n", &lo, &n, &hi, &n);
901 [ # # ]: 0 : if (result == 1) {
902 [ # # ]: 0 : if (lo >= IDPF_MAX_VPORT_NUM)
903 : : return NULL;
904 [ # # ]: 0 : if (insert_value(devargs, lo) != 0)
905 : : return NULL;
906 [ # # ]: 0 : } else if (result == 2) {
907 [ # # # # ]: 0 : if (lo > hi || hi >= IDPF_MAX_VPORT_NUM)
908 : : return NULL;
909 [ # # ]: 0 : for (i = lo; i <= hi; i++) {
910 [ # # ]: 0 : if (insert_value(devargs, i) != 0)
911 : : return NULL;
912 : : }
913 : : } else {
914 : : return NULL;
915 : : }
916 : :
917 : 0 : return pos + n;
918 : : }
919 : :
920 : : static int
921 : 0 : parse_vport(const char *key, const char *value, void *args)
922 : : {
923 : : struct idpf_devargs *devargs = args;
924 : : const char *pos = value;
925 : :
926 : 0 : devargs->req_vport_nb = 0;
927 : :
928 [ # # ]: 0 : if (*pos == '[')
929 : 0 : pos++;
930 : :
931 : : while (1) {
932 : 0 : pos = parse_range(pos, devargs);
933 [ # # ]: 0 : if (pos == NULL) {
934 : 0 : PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", ",
935 : : value, key);
936 : 0 : return -EINVAL;
937 : : }
938 [ # # ]: 0 : if (*pos != ',')
939 : : break;
940 : 0 : pos++;
941 : : }
942 : :
943 [ # # # # ]: 0 : if (*value == '[' && *pos != ']') {
944 : 0 : PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", ",
945 : : value, key);
946 : 0 : return -EINVAL;
947 : : }
948 : :
949 : : return 0;
950 : : }
951 : :
952 : : static int
953 : 0 : parse_bool(const char *key, const char *value, void *args)
954 : : {
955 : : int *i = args;
956 : : char *end;
957 : : int num;
958 : :
959 : 0 : errno = 0;
960 : :
961 : 0 : num = strtoul(value, &end, 10);
962 : :
963 [ # # # # ]: 0 : if (errno == ERANGE || (num != 0 && num != 1)) {
964 : 0 : PMD_INIT_LOG(ERR, "invalid value:\"%s\" for key:\"%s\", value must be 0 or 1",
965 : : value, key);
966 : 0 : return -EINVAL;
967 : : }
968 : :
969 : 0 : *i = num;
970 : 0 : return 0;
971 : : }
972 : :
973 : : static int
974 : 0 : idpf_parse_devargs(struct rte_pci_device *pci_dev, struct idpf_adapter_ext *adapter,
975 : : struct idpf_devargs *idpf_args)
976 : : {
977 : 0 : struct rte_devargs *devargs = pci_dev->device.devargs;
978 : : struct rte_kvargs *kvlist;
979 : : int i, ret;
980 : :
981 : 0 : idpf_args->req_vport_nb = 0;
982 : :
983 [ # # ]: 0 : if (devargs == NULL)
984 : : return 0;
985 : :
986 : 0 : kvlist = rte_kvargs_parse(devargs->args, idpf_valid_args);
987 [ # # ]: 0 : if (kvlist == NULL) {
988 : 0 : PMD_INIT_LOG(ERR, "invalid kvargs key");
989 : 0 : return -EINVAL;
990 : : }
991 : :
992 : : /* check parsed devargs */
993 [ # # ]: 0 : if (adapter->cur_vport_nb + idpf_args->req_vport_nb >
994 : : IDPF_MAX_VPORT_NUM) {
995 : 0 : PMD_INIT_LOG(ERR, "Total vport number can't be > %d",
996 : : IDPF_MAX_VPORT_NUM);
997 : : ret = -EINVAL;
998 : 0 : goto bail;
999 : : }
1000 : :
1001 [ # # ]: 0 : for (i = 0; i < idpf_args->req_vport_nb; i++) {
1002 [ # # ]: 0 : if (adapter->cur_vports & RTE_BIT32(idpf_args->req_vports[i])) {
1003 : 0 : PMD_INIT_LOG(ERR, "Vport %d has been created",
1004 : : idpf_args->req_vports[i]);
1005 : : ret = -EINVAL;
1006 : 0 : goto bail;
1007 : : }
1008 : : }
1009 : :
1010 : 0 : ret = rte_kvargs_process(kvlist, IDPF_VPORT, &parse_vport,
1011 : : idpf_args);
1012 [ # # ]: 0 : if (ret != 0)
1013 : 0 : goto bail;
1014 : :
1015 : 0 : ret = rte_kvargs_process(kvlist, IDPF_TX_SINGLE_Q, &parse_bool,
1016 : 0 : &adapter->base.is_tx_singleq);
1017 [ # # ]: 0 : if (ret != 0)
1018 : 0 : goto bail;
1019 : :
1020 : 0 : ret = rte_kvargs_process(kvlist, IDPF_RX_SINGLE_Q, &parse_bool,
1021 : 0 : &adapter->base.is_rx_singleq);
1022 [ # # ]: 0 : if (ret != 0)
1023 : 0 : goto bail;
1024 : :
1025 : 0 : bail:
1026 : 0 : rte_kvargs_free(kvlist);
1027 : 0 : return ret;
1028 : : }
1029 : :
1030 : : static struct idpf_vport *
1031 : : idpf_find_vport(struct idpf_adapter_ext *adapter, uint32_t vport_id)
1032 : : {
1033 : : struct idpf_vport *vport = NULL;
1034 : : int i;
1035 : :
1036 [ # # ]: 0 : for (i = 0; i < adapter->cur_vport_nb; i++) {
1037 : 0 : vport = adapter->vports[i];
1038 [ # # ]: 0 : if (vport->vport_id != vport_id)
1039 : : continue;
1040 : : else
1041 : : return vport;
1042 : : }
1043 : :
1044 : : return vport;
1045 : : }
1046 : :
1047 : : static void
1048 : 0 : idpf_handle_event_msg(struct idpf_vport *vport, uint8_t *msg, uint16_t msglen)
1049 : : {
1050 : : struct virtchnl2_event *vc_event = (struct virtchnl2_event *)msg;
1051 : 0 : struct rte_eth_dev_data *data = vport->dev_data;
1052 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[data->port_id];
1053 : :
1054 [ # # ]: 0 : if (msglen < sizeof(struct virtchnl2_event)) {
1055 : 0 : PMD_DRV_LOG(ERR, "Error event");
1056 : 0 : return;
1057 : : }
1058 : :
1059 [ # # ]: 0 : switch (vc_event->event) {
1060 : 0 : case VIRTCHNL2_EVENT_LINK_CHANGE:
1061 : 0 : PMD_DRV_LOG(DEBUG, "VIRTCHNL2_EVENT_LINK_CHANGE");
1062 : 0 : vport->link_up = !!(vc_event->link_status);
1063 : 0 : vport->link_speed = vc_event->link_speed;
1064 : 0 : idpf_dev_link_update(dev, 0);
1065 : 0 : break;
1066 : 0 : default:
1067 : 0 : PMD_DRV_LOG(ERR, " unknown event received %u", vc_event->event);
1068 : 0 : break;
1069 : : }
1070 : : }
1071 : :
1072 : : static void
1073 : 0 : idpf_handle_virtchnl_msg(struct idpf_adapter_ext *adapter_ex)
1074 : : {
1075 : : struct idpf_adapter *adapter = &adapter_ex->base;
1076 : 0 : struct idpf_dma_mem *dma_mem = NULL;
1077 : 0 : struct idpf_hw *hw = &adapter->hw;
1078 : : struct virtchnl2_event *vc_event;
1079 : : struct idpf_ctlq_msg ctlq_msg;
1080 : : enum idpf_mbx_opc mbx_op;
1081 : : struct idpf_vport *vport;
1082 : 0 : uint16_t pending = 1;
1083 : : uint32_t vc_op;
1084 : : int ret;
1085 : :
1086 [ # # ]: 0 : while (pending) {
1087 : 0 : ret = idpf_vc_ctlq_recv(hw->arq, &pending, &ctlq_msg);
1088 [ # # ]: 0 : if (ret) {
1089 : 0 : PMD_DRV_LOG(INFO, "Failed to read msg from virtual channel, ret: %d", ret);
1090 : 0 : return;
1091 : : }
1092 : :
1093 [ # # ]: 0 : rte_memcpy(adapter->mbx_resp, ctlq_msg.ctx.indirect.payload->va,
1094 : : IDPF_DFLT_MBX_BUF_SIZE);
1095 : :
1096 : 0 : mbx_op = rte_le_to_cpu_16(ctlq_msg.opcode);
1097 : 0 : vc_op = rte_le_to_cpu_32(ctlq_msg.cookie.mbx.chnl_opcode);
1098 : 0 : adapter->cmd_retval = rte_le_to_cpu_32(ctlq_msg.cookie.mbx.chnl_retval);
1099 : :
1100 [ # # ]: 0 : switch (mbx_op) {
1101 : 0 : case idpf_mbq_opc_send_msg_to_peer_pf:
1102 : : case idpf_mbq_opc_send_msg_to_peer_drv:
1103 [ # # ]: 0 : if (vc_op == VIRTCHNL2_OP_EVENT) {
1104 [ # # ]: 0 : if (ctlq_msg.data_len < sizeof(struct virtchnl2_event)) {
1105 : 0 : PMD_DRV_LOG(ERR, "Error event");
1106 : 0 : return;
1107 : : }
1108 : 0 : vc_event = (struct virtchnl2_event *)adapter->mbx_resp;
1109 : 0 : vport = idpf_find_vport(adapter_ex, vc_event->vport_id);
1110 [ # # ]: 0 : if (!vport) {
1111 : 0 : PMD_DRV_LOG(ERR, "Can't find vport.");
1112 : 0 : return;
1113 : : }
1114 : 0 : idpf_handle_event_msg(vport, adapter->mbx_resp,
1115 : : ctlq_msg.data_len);
1116 : : } else {
1117 [ # # ]: 0 : if (vc_op == adapter->pend_cmd)
1118 : : notify_cmd(adapter, adapter->cmd_retval);
1119 : : else
1120 : 0 : PMD_DRV_LOG(ERR, "command mismatch, expect %u, get %u",
1121 : : adapter->pend_cmd, vc_op);
1122 : :
1123 : 0 : PMD_DRV_LOG(DEBUG, " Virtual channel response is received,"
1124 : : "opcode = %d", vc_op);
1125 : : }
1126 : 0 : goto post_buf;
1127 : 0 : default:
1128 : 0 : PMD_DRV_LOG(DEBUG, "Request %u is not supported yet", mbx_op);
1129 : : }
1130 : : }
1131 : :
1132 : 0 : post_buf:
1133 [ # # ]: 0 : if (ctlq_msg.data_len)
1134 : 0 : dma_mem = ctlq_msg.ctx.indirect.payload;
1135 : : else
1136 : 0 : pending = 0;
1137 : :
1138 : 0 : ret = idpf_vc_ctlq_post_rx_buffs(hw, hw->arq, &pending, &dma_mem);
1139 [ # # # # ]: 0 : if (ret && dma_mem)
1140 : : idpf_free_dma_mem(hw, dma_mem);
1141 : : }
1142 : :
1143 : : static void
1144 : 0 : idpf_dev_alarm_handler(void *param)
1145 : : {
1146 : : struct idpf_adapter_ext *adapter = param;
1147 : :
1148 : 0 : idpf_handle_virtchnl_msg(adapter);
1149 : :
1150 : 0 : rte_eal_alarm_set(IDPF_ALARM_INTERVAL, idpf_dev_alarm_handler, adapter);
1151 : 0 : }
1152 : :
1153 : : static struct virtchnl2_get_capabilities req_caps = {
1154 : : .csum_caps =
1155 : : VIRTCHNL2_CAP_TX_CSUM_L3_IPV4 |
1156 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_TCP |
1157 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_UDP |
1158 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV4_SCTP |
1159 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_TCP |
1160 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_UDP |
1161 : : VIRTCHNL2_CAP_TX_CSUM_L4_IPV6_SCTP |
1162 : : VIRTCHNL2_CAP_TX_CSUM_GENERIC |
1163 : : VIRTCHNL2_CAP_RX_CSUM_L3_IPV4 |
1164 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_TCP |
1165 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_UDP |
1166 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV4_SCTP |
1167 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_TCP |
1168 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_UDP |
1169 : : VIRTCHNL2_CAP_RX_CSUM_L4_IPV6_SCTP |
1170 : : VIRTCHNL2_CAP_RX_CSUM_GENERIC,
1171 : :
1172 : : .rss_caps =
1173 : : VIRTCHNL2_CAP_RSS_IPV4_TCP |
1174 : : VIRTCHNL2_CAP_RSS_IPV4_UDP |
1175 : : VIRTCHNL2_CAP_RSS_IPV4_SCTP |
1176 : : VIRTCHNL2_CAP_RSS_IPV4_OTHER |
1177 : : VIRTCHNL2_CAP_RSS_IPV6_TCP |
1178 : : VIRTCHNL2_CAP_RSS_IPV6_UDP |
1179 : : VIRTCHNL2_CAP_RSS_IPV6_SCTP |
1180 : : VIRTCHNL2_CAP_RSS_IPV6_OTHER |
1181 : : VIRTCHNL2_CAP_RSS_IPV4_AH |
1182 : : VIRTCHNL2_CAP_RSS_IPV4_ESP |
1183 : : VIRTCHNL2_CAP_RSS_IPV4_AH_ESP |
1184 : : VIRTCHNL2_CAP_RSS_IPV6_AH |
1185 : : VIRTCHNL2_CAP_RSS_IPV6_ESP |
1186 : : VIRTCHNL2_CAP_RSS_IPV6_AH_ESP,
1187 : :
1188 : : .other_caps = VIRTCHNL2_CAP_WB_ON_ITR
1189 : : };
1190 : :
1191 : : static int
1192 : 0 : idpf_adapter_ext_init(struct rte_pci_device *pci_dev, struct idpf_adapter_ext *adapter)
1193 : : {
1194 : 0 : struct idpf_adapter *base = &adapter->base;
1195 : : struct idpf_hw *hw = &base->hw;
1196 : : int ret = 0;
1197 : :
1198 : 0 : hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
1199 : 0 : hw->hw_addr_len = pci_dev->mem_resource[0].len;
1200 : 0 : hw->back = base;
1201 : 0 : hw->vendor_id = pci_dev->id.vendor_id;
1202 : 0 : hw->device_id = pci_dev->id.device_id;
1203 : 0 : hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
1204 : :
1205 [ # # ]: 0 : strncpy(adapter->name, pci_dev->device.name, PCI_PRI_STR_SIZE);
1206 : :
1207 [ # # ]: 0 : rte_memcpy(&base->caps, &req_caps, sizeof(struct virtchnl2_get_capabilities));
1208 : :
1209 : 0 : ret = idpf_adapter_init(base);
1210 [ # # ]: 0 : if (ret != 0) {
1211 : 0 : PMD_INIT_LOG(ERR, "Failed to init adapter");
1212 : 0 : goto err_adapter_init;
1213 : : }
1214 : :
1215 : 0 : rte_eal_alarm_set(IDPF_ALARM_INTERVAL, idpf_dev_alarm_handler, adapter);
1216 : :
1217 : 0 : adapter->max_vport_nb = adapter->base.caps.max_vports;
1218 : :
1219 : 0 : adapter->vports = rte_zmalloc("vports",
1220 : 0 : adapter->max_vport_nb *
1221 : : sizeof(*adapter->vports),
1222 : : 0);
1223 [ # # ]: 0 : if (adapter->vports == NULL) {
1224 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate vports memory");
1225 : : ret = -ENOMEM;
1226 : 0 : goto err_vports_alloc;
1227 : : }
1228 : :
1229 : 0 : adapter->cur_vports = 0;
1230 : 0 : adapter->cur_vport_nb = 0;
1231 : :
1232 : 0 : adapter->used_vecs_num = 0;
1233 : :
1234 : 0 : return ret;
1235 : :
1236 : : err_vports_alloc:
1237 : 0 : rte_eal_alarm_cancel(idpf_dev_alarm_handler, adapter);
1238 : 0 : idpf_adapter_deinit(base);
1239 : : err_adapter_init:
1240 : : return ret;
1241 : : }
1242 : :
1243 : : static uint16_t
1244 : : idpf_vport_idx_alloc(struct idpf_adapter_ext *ad)
1245 : : {
1246 : : uint16_t vport_idx;
1247 : : uint16_t i;
1248 : :
1249 [ # # # # ]: 0 : for (i = 0; i < ad->max_vport_nb; i++) {
1250 [ # # # # ]: 0 : if (ad->vports[i] == NULL)
1251 : : break;
1252 : : }
1253 : :
1254 [ # # # # ]: 0 : if (i == ad->max_vport_nb)
1255 : : vport_idx = IDPF_INVALID_VPORT_IDX;
1256 : : else
1257 : : vport_idx = i;
1258 : :
1259 : : return vport_idx;
1260 : : }
1261 : :
1262 : : static int
1263 : 0 : idpf_dev_vport_init(struct rte_eth_dev *dev, void *init_params)
1264 : : {
1265 : 0 : struct idpf_vport *vport = dev->data->dev_private;
1266 : : struct idpf_vport_param *param = init_params;
1267 : 0 : struct idpf_adapter_ext *adapter = param->adapter;
1268 : : /* for sending create vport virtchnl msg prepare */
1269 : : struct virtchnl2_create_vport create_vport_info;
1270 : : int ret = 0;
1271 : :
1272 : 0 : dev->dev_ops = &idpf_eth_dev_ops;
1273 : 0 : vport->adapter = &adapter->base;
1274 : 0 : vport->sw_idx = param->idx;
1275 : 0 : vport->devarg_id = param->devarg_id;
1276 : :
1277 : : memset(&create_vport_info, 0, sizeof(create_vport_info));
1278 : 0 : ret = idpf_vport_info_init(vport, &create_vport_info);
1279 [ # # ]: 0 : if (ret != 0) {
1280 : 0 : PMD_INIT_LOG(ERR, "Failed to init vport req_info.");
1281 : 0 : goto err;
1282 : : }
1283 : :
1284 : 0 : ret = idpf_vport_init(vport, &create_vport_info, dev->data);
1285 [ # # ]: 0 : if (ret != 0) {
1286 : 0 : PMD_INIT_LOG(ERR, "Failed to init vports.");
1287 : 0 : goto err;
1288 : : }
1289 : :
1290 : 0 : dev->data->mac_addrs = rte_zmalloc(NULL, RTE_ETHER_ADDR_LEN, 0);
1291 [ # # ]: 0 : if (dev->data->mac_addrs == NULL) {
1292 : 0 : PMD_INIT_LOG(ERR, "Cannot allocate mac_addr memory.");
1293 : : ret = -ENOMEM;
1294 : 0 : goto err_mac_addrs;
1295 : : }
1296 : :
1297 : : rte_ether_addr_copy((struct rte_ether_addr *)vport->default_mac_addr,
1298 : : &dev->data->mac_addrs[0]);
1299 : :
1300 : 0 : adapter->vports[param->idx] = vport;
1301 : 0 : adapter->cur_vports |= RTE_BIT32(param->devarg_id);
1302 : 0 : adapter->cur_vport_nb++;
1303 : :
1304 : 0 : return 0;
1305 : :
1306 : : err_mac_addrs:
1307 : 0 : adapter->vports[param->idx] = NULL; /* reset */
1308 : 0 : idpf_vport_deinit(vport);
1309 : : err:
1310 : : return ret;
1311 : : }
1312 : :
1313 : : static const struct rte_pci_id pci_id_idpf_map[] = {
1314 : : { RTE_PCI_DEVICE(IDPF_INTEL_VENDOR_ID, IDPF_DEV_ID_PF) },
1315 : : { RTE_PCI_DEVICE(IDPF_INTEL_VENDOR_ID, IDPF_DEV_ID_SRIOV) },
1316 : : { .vendor_id = 0, /* sentinel */ },
1317 : : };
1318 : :
1319 : : static struct idpf_adapter_ext *
1320 : 0 : idpf_find_adapter_ext(struct rte_pci_device *pci_dev)
1321 : : {
1322 : : struct idpf_adapter_ext *adapter;
1323 : : int found = 0;
1324 : :
1325 [ # # ]: 0 : if (pci_dev == NULL)
1326 : : return NULL;
1327 : :
1328 : : rte_spinlock_lock(&idpf_adapter_lock);
1329 [ # # ]: 0 : TAILQ_FOREACH(adapter, &idpf_adapter_list, next) {
1330 [ # # ]: 0 : if (strncmp(adapter->name, pci_dev->device.name, PCI_PRI_STR_SIZE) == 0) {
1331 : : found = 1;
1332 : : break;
1333 : : }
1334 : : }
1335 : : rte_spinlock_unlock(&idpf_adapter_lock);
1336 : :
1337 [ # # ]: 0 : if (found == 0)
1338 : 0 : return NULL;
1339 : :
1340 : : return adapter;
1341 : : }
1342 : :
1343 : : static void
1344 : 0 : idpf_adapter_ext_deinit(struct idpf_adapter_ext *adapter)
1345 : : {
1346 : 0 : rte_eal_alarm_cancel(idpf_dev_alarm_handler, adapter);
1347 : 0 : idpf_adapter_deinit(&adapter->base);
1348 : :
1349 : 0 : rte_free(adapter->vports);
1350 : 0 : adapter->vports = NULL;
1351 : 0 : }
1352 : :
1353 : : static int
1354 : 0 : idpf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
1355 : : struct rte_pci_device *pci_dev)
1356 : : {
1357 : : struct idpf_vport_param vport_param;
1358 : : struct idpf_adapter_ext *adapter;
1359 : : struct idpf_devargs devargs;
1360 : : char name[RTE_ETH_NAME_MAX_LEN];
1361 : : int i, retval;
1362 : : bool first_probe = false;
1363 : :
1364 [ # # ]: 0 : if (!idpf_adapter_list_init) {
1365 : : rte_spinlock_init(&idpf_adapter_lock);
1366 : 0 : TAILQ_INIT(&idpf_adapter_list);
1367 : 0 : idpf_adapter_list_init = true;
1368 : : }
1369 : :
1370 : 0 : adapter = idpf_find_adapter_ext(pci_dev);
1371 [ # # ]: 0 : if (adapter == NULL) {
1372 : : first_probe = true;
1373 : 0 : adapter = rte_zmalloc("idpf_adapter_ext",
1374 : : sizeof(struct idpf_adapter_ext), 0);
1375 [ # # ]: 0 : if (adapter == NULL) {
1376 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate adapter.");
1377 : 0 : return -ENOMEM;
1378 : : }
1379 : :
1380 : 0 : retval = idpf_adapter_ext_init(pci_dev, adapter);
1381 [ # # ]: 0 : if (retval != 0) {
1382 : 0 : PMD_INIT_LOG(ERR, "Failed to init adapter.");
1383 : 0 : return retval;
1384 : : }
1385 : :
1386 : : rte_spinlock_lock(&idpf_adapter_lock);
1387 : 0 : TAILQ_INSERT_TAIL(&idpf_adapter_list, adapter, next);
1388 : : rte_spinlock_unlock(&idpf_adapter_lock);
1389 : : }
1390 : :
1391 : 0 : retval = idpf_parse_devargs(pci_dev, adapter, &devargs);
1392 [ # # ]: 0 : if (retval != 0) {
1393 : 0 : PMD_INIT_LOG(ERR, "Failed to parse private devargs");
1394 : 0 : goto err;
1395 : : }
1396 : :
1397 [ # # ]: 0 : if (devargs.req_vport_nb == 0) {
1398 : : /* If no vport devarg, create vport 0 by default. */
1399 : 0 : vport_param.adapter = adapter;
1400 : 0 : vport_param.devarg_id = 0;
1401 : 0 : vport_param.idx = idpf_vport_idx_alloc(adapter);
1402 [ # # ]: 0 : if (vport_param.idx == IDPF_INVALID_VPORT_IDX) {
1403 : 0 : PMD_INIT_LOG(ERR, "No space for vport %u", vport_param.devarg_id);
1404 : 0 : return 0;
1405 : : }
1406 : 0 : snprintf(name, sizeof(name), "idpf_%s_vport_0",
1407 : : pci_dev->device.name);
1408 : 0 : retval = rte_eth_dev_create(&pci_dev->device, name,
1409 : : sizeof(struct idpf_vport),
1410 : : NULL, NULL, idpf_dev_vport_init,
1411 : : &vport_param);
1412 [ # # ]: 0 : if (retval != 0)
1413 : 0 : PMD_DRV_LOG(ERR, "Failed to create default vport 0");
1414 : : } else {
1415 [ # # ]: 0 : for (i = 0; i < devargs.req_vport_nb; i++) {
1416 : 0 : vport_param.adapter = adapter;
1417 : 0 : vport_param.devarg_id = devargs.req_vports[i];
1418 : 0 : vport_param.idx = idpf_vport_idx_alloc(adapter);
1419 [ # # ]: 0 : if (vport_param.idx == IDPF_INVALID_VPORT_IDX) {
1420 : 0 : PMD_INIT_LOG(ERR, "No space for vport %u", vport_param.devarg_id);
1421 : 0 : break;
1422 : : }
1423 : 0 : snprintf(name, sizeof(name), "idpf_%s_vport_%d",
1424 : : pci_dev->device.name,
1425 : : devargs.req_vports[i]);
1426 : 0 : retval = rte_eth_dev_create(&pci_dev->device, name,
1427 : : sizeof(struct idpf_vport),
1428 : : NULL, NULL, idpf_dev_vport_init,
1429 : : &vport_param);
1430 [ # # ]: 0 : if (retval != 0)
1431 : 0 : PMD_DRV_LOG(ERR, "Failed to create vport %d",
1432 : : vport_param.devarg_id);
1433 : : }
1434 : : }
1435 : :
1436 : : return 0;
1437 : :
1438 : : err:
1439 [ # # ]: 0 : if (first_probe) {
1440 : : rte_spinlock_lock(&idpf_adapter_lock);
1441 [ # # ]: 0 : TAILQ_REMOVE(&idpf_adapter_list, adapter, next);
1442 : : rte_spinlock_unlock(&idpf_adapter_lock);
1443 : 0 : idpf_adapter_ext_deinit(adapter);
1444 : 0 : rte_free(adapter);
1445 : : }
1446 : : return retval;
1447 : : }
1448 : :
1449 : : static int
1450 : 0 : idpf_pci_remove(struct rte_pci_device *pci_dev)
1451 : : {
1452 : 0 : struct idpf_adapter_ext *adapter = idpf_find_adapter_ext(pci_dev);
1453 : : uint16_t port_id;
1454 : :
1455 : : /* Ethdev created can be found RTE_ETH_FOREACH_DEV_OF through rte_device */
1456 [ # # ]: 0 : RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) {
1457 : 0 : rte_eth_dev_close(port_id);
1458 : : }
1459 : :
1460 : : rte_spinlock_lock(&idpf_adapter_lock);
1461 [ # # ]: 0 : TAILQ_REMOVE(&idpf_adapter_list, adapter, next);
1462 : : rte_spinlock_unlock(&idpf_adapter_lock);
1463 : 0 : idpf_adapter_ext_deinit(adapter);
1464 : 0 : rte_free(adapter);
1465 : :
1466 : 0 : return 0;
1467 : : }
1468 : :
1469 : : static struct rte_pci_driver rte_idpf_pmd = {
1470 : : .id_table = pci_id_idpf_map,
1471 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
1472 : : .probe = idpf_pci_probe,
1473 : : .remove = idpf_pci_remove,
1474 : : };
1475 : :
1476 : : /**
1477 : : * Driver initialization routine.
1478 : : * Invoked once at EAL init time.
1479 : : * Register itself as the [Poll Mode] Driver of PCI devices.
1480 : : */
1481 : 252 : RTE_PMD_REGISTER_PCI(net_idpf, rte_idpf_pmd);
1482 : : RTE_PMD_REGISTER_PCI_TABLE(net_idpf, pci_id_idpf_map);
1483 : : RTE_PMD_REGISTER_KMOD_DEP(net_idpf, "* igb_uio | vfio-pci");
1484 : : RTE_PMD_REGISTER_PARAM_STRING(net_idpf,
1485 : : IDPF_TX_SINGLE_Q "=<0|1> "
1486 : : IDPF_RX_SINGLE_Q "=<0|1> "
1487 : : IDPF_VPORT "=[<begin>[-<end>][,<begin >[-<end>]][, ... ]]");
1488 : :
1489 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(idpf_logtype_init, init, NOTICE);
1490 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(idpf_logtype_driver, driver, NOTICE);
|