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