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