xref: /dpdk/drivers/net/virtio/virtio_pci.c (revision bf56fce1fb45b83747527e6312f61c0fcf3789b8)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <stdint.h>
34 
35 #ifdef RTE_EXEC_ENV_LINUXAPP
36  #include <dirent.h>
37  #include <fcntl.h>
38 #endif
39 
40 #include "virtio_pci.h"
41 #include "virtio_logs.h"
42 #include "virtqueue.h"
43 
44 /*
45  * Following macros are derived from linux/pci_regs.h, however,
46  * we can't simply include that header here, as there is no such
47  * file for non-Linux platform.
48  */
49 #define PCI_CAPABILITY_LIST	0x34
50 #define PCI_CAP_ID_VNDR		0x09
51 
52 /*
53  * The remaining space is defined by each driver as the per-driver
54  * configuration space.
55  */
56 #define VIRTIO_PCI_CONFIG(hw) (((hw)->use_msix) ? 24 : 20)
57 
58 /*
59  * Since we are in legacy mode:
60  * http://ozlabs.org/~rusty/virtio-spec/virtio-0.9.5.pdf
61  *
62  * "Note that this is possible because while the virtio header is PCI (i.e.
63  * little) endian, the device-specific region is encoded in the native endian of
64  * the guest (where such distinction is applicable)."
65  *
66  * For powerpc which supports both, qemu supposes that cpu is big endian and
67  * enforces this for the virtio-net stuff.
68  */
69 
70 static void
71 legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
72 		       void *dst, int length)
73 {
74 #ifdef RTE_ARCH_PPC_64
75 	int size;
76 
77 	while (length > 0) {
78 		if (length >= 4) {
79 			size = 4;
80 			rte_eal_pci_ioport_read(&hw->io, dst, size,
81 				VIRTIO_PCI_CONFIG(hw) + offset);
82 			*(uint32_t *)dst = rte_be_to_cpu_32(*(uint32_t *)dst);
83 		} else if (length >= 2) {
84 			size = 2;
85 			rte_eal_pci_ioport_read(&hw->io, dst, size,
86 				VIRTIO_PCI_CONFIG(hw) + offset);
87 			*(uint16_t *)dst = rte_be_to_cpu_16(*(uint16_t *)dst);
88 		} else {
89 			size = 1;
90 			rte_eal_pci_ioport_read(&hw->io, dst, size,
91 				VIRTIO_PCI_CONFIG(hw) + offset);
92 		}
93 
94 		dst = (char *)dst + size;
95 		offset += size;
96 		length -= size;
97 	}
98 #else
99 	rte_eal_pci_ioport_read(&hw->io, dst, length,
100 				VIRTIO_PCI_CONFIG(hw) + offset);
101 #endif
102 }
103 
104 static void
105 legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
106 			const void *src, int length)
107 {
108 #ifdef RTE_ARCH_PPC_64
109 	union {
110 		uint32_t u32;
111 		uint16_t u16;
112 	} tmp;
113 	int size;
114 
115 	while (length > 0) {
116 		if (length >= 4) {
117 			size = 4;
118 			tmp.u32 = rte_cpu_to_be_32(*(const uint32_t *)src);
119 			rte_eal_pci_ioport_write(&hw->io, &tmp.u32, size,
120 				VIRTIO_PCI_CONFIG(hw) + offset);
121 		} else if (length >= 2) {
122 			size = 2;
123 			tmp.u16 = rte_cpu_to_be_16(*(const uint16_t *)src);
124 			rte_eal_pci_ioport_write(&hw->io, &tmp.u16, size,
125 				VIRTIO_PCI_CONFIG(hw) + offset);
126 		} else {
127 			size = 1;
128 			rte_eal_pci_ioport_write(&hw->io, src, size,
129 				VIRTIO_PCI_CONFIG(hw) + offset);
130 		}
131 
132 		src = (const char *)src + size;
133 		offset += size;
134 		length -= size;
135 	}
136 #else
137 	rte_eal_pci_ioport_write(&hw->io, src, length,
138 				 VIRTIO_PCI_CONFIG(hw) + offset);
139 #endif
140 }
141 
142 static uint64_t
143 legacy_get_features(struct virtio_hw *hw)
144 {
145 	uint32_t dst;
146 
147 	rte_eal_pci_ioport_read(&hw->io, &dst, 4, VIRTIO_PCI_HOST_FEATURES);
148 	return dst;
149 }
150 
151 static void
152 legacy_set_features(struct virtio_hw *hw, uint64_t features)
153 {
154 	if ((features >> 32) != 0) {
155 		PMD_DRV_LOG(ERR,
156 			"only 32 bit features are allowed for legacy virtio!");
157 		return;
158 	}
159 	rte_eal_pci_ioport_write(&hw->io, &features, 4,
160 				 VIRTIO_PCI_GUEST_FEATURES);
161 }
162 
163 static uint8_t
164 legacy_get_status(struct virtio_hw *hw)
165 {
166 	uint8_t dst;
167 
168 	rte_eal_pci_ioport_read(&hw->io, &dst, 1, VIRTIO_PCI_STATUS);
169 	return dst;
170 }
171 
172 static void
173 legacy_set_status(struct virtio_hw *hw, uint8_t status)
174 {
175 	rte_eal_pci_ioport_write(&hw->io, &status, 1, VIRTIO_PCI_STATUS);
176 }
177 
178 static void
179 legacy_reset(struct virtio_hw *hw)
180 {
181 	legacy_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
182 }
183 
184 static uint8_t
185 legacy_get_isr(struct virtio_hw *hw)
186 {
187 	uint8_t dst;
188 
189 	rte_eal_pci_ioport_read(&hw->io, &dst, 1, VIRTIO_PCI_ISR);
190 	return dst;
191 }
192 
193 /* Enable one vector (0) for Link State Intrerrupt */
194 static uint16_t
195 legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
196 {
197 	uint16_t dst;
198 
199 	rte_eal_pci_ioport_write(&hw->io, &vec, 2, VIRTIO_MSI_CONFIG_VECTOR);
200 	rte_eal_pci_ioport_read(&hw->io, &dst, 2, VIRTIO_MSI_CONFIG_VECTOR);
201 	return dst;
202 }
203 
204 static uint16_t
205 legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
206 {
207 	uint16_t dst;
208 
209 	rte_eal_pci_ioport_write(&hw->io, &queue_id, 2, VIRTIO_PCI_QUEUE_SEL);
210 	rte_eal_pci_ioport_read(&hw->io, &dst, 2, VIRTIO_PCI_QUEUE_NUM);
211 	return dst;
212 }
213 
214 static void
215 legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
216 {
217 	uint32_t src;
218 
219 	rte_eal_pci_ioport_write(&hw->io, &vq->vq_queue_index, 2,
220 			 VIRTIO_PCI_QUEUE_SEL);
221 	src = vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
222 	rte_eal_pci_ioport_write(&hw->io, &src, 4, VIRTIO_PCI_QUEUE_PFN);
223 }
224 
225 static void
226 legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
227 {
228 	uint32_t src = 0;
229 
230 	rte_eal_pci_ioport_write(&hw->io, &vq->vq_queue_index, 2,
231 			 VIRTIO_PCI_QUEUE_SEL);
232 	rte_eal_pci_ioport_write(&hw->io, &src, 4, VIRTIO_PCI_QUEUE_PFN);
233 }
234 
235 static void
236 legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
237 {
238 	rte_eal_pci_ioport_write(&hw->io, &vq->vq_queue_index, 2,
239 			 VIRTIO_PCI_QUEUE_NOTIFY);
240 }
241 
242 #ifdef RTE_EXEC_ENV_LINUXAPP
243 static int
244 legacy_virtio_has_msix(const struct rte_pci_addr *loc)
245 {
246 	DIR *d;
247 	char dirname[PATH_MAX];
248 
249 	snprintf(dirname, sizeof(dirname),
250 		     "%s/" PCI_PRI_FMT "/msi_irqs", pci_get_sysfs_path(),
251 		     loc->domain, loc->bus, loc->devid, loc->function);
252 
253 	d = opendir(dirname);
254 	if (d)
255 		closedir(d);
256 
257 	return d != NULL;
258 }
259 #else
260 static int
261 legacy_virtio_has_msix(const struct rte_pci_addr *loc __rte_unused)
262 {
263 	/* nic_uio does not enable interrupts, return 0 (false). */
264 	return 0;
265 }
266 #endif
267 
268 static int
269 legacy_virtio_resource_init(struct rte_pci_device *pci_dev,
270 			    struct virtio_hw *hw, uint32_t *dev_flags)
271 {
272 	if (rte_eal_pci_ioport_map(pci_dev, 0, &hw->io) < 0)
273 		return -1;
274 
275 	if (pci_dev->intr_handle.type != RTE_INTR_HANDLE_UNKNOWN)
276 		*dev_flags |= RTE_ETH_DEV_INTR_LSC;
277 	else
278 		*dev_flags &= ~RTE_ETH_DEV_INTR_LSC;
279 
280 	return 0;
281 }
282 
283 static const struct virtio_pci_ops legacy_ops = {
284 	.read_dev_cfg	= legacy_read_dev_config,
285 	.write_dev_cfg	= legacy_write_dev_config,
286 	.reset		= legacy_reset,
287 	.get_status	= legacy_get_status,
288 	.set_status	= legacy_set_status,
289 	.get_features	= legacy_get_features,
290 	.set_features	= legacy_set_features,
291 	.get_isr	= legacy_get_isr,
292 	.set_config_irq	= legacy_set_config_irq,
293 	.get_queue_num	= legacy_get_queue_num,
294 	.setup_queue	= legacy_setup_queue,
295 	.del_queue	= legacy_del_queue,
296 	.notify_queue	= legacy_notify_queue,
297 };
298 
299 
300 static inline uint8_t
301 io_read8(uint8_t *addr)
302 {
303 	return *(volatile uint8_t *)addr;
304 }
305 
306 static inline void
307 io_write8(uint8_t val, uint8_t *addr)
308 {
309 	*(volatile uint8_t *)addr = val;
310 }
311 
312 static inline uint16_t
313 io_read16(uint16_t *addr)
314 {
315 	return *(volatile uint16_t *)addr;
316 }
317 
318 static inline void
319 io_write16(uint16_t val, uint16_t *addr)
320 {
321 	*(volatile uint16_t *)addr = val;
322 }
323 
324 static inline uint32_t
325 io_read32(uint32_t *addr)
326 {
327 	return *(volatile uint32_t *)addr;
328 }
329 
330 static inline void
331 io_write32(uint32_t val, uint32_t *addr)
332 {
333 	*(volatile uint32_t *)addr = val;
334 }
335 
336 static inline void
337 io_write64_twopart(uint64_t val, uint32_t *lo, uint32_t *hi)
338 {
339 	io_write32(val & ((1ULL << 32) - 1), lo);
340 	io_write32(val >> 32,		     hi);
341 }
342 
343 static void
344 modern_read_dev_config(struct virtio_hw *hw, size_t offset,
345 		       void *dst, int length)
346 {
347 	int i;
348 	uint8_t *p;
349 	uint8_t old_gen, new_gen;
350 
351 	do {
352 		old_gen = io_read8(&hw->common_cfg->config_generation);
353 
354 		p = dst;
355 		for (i = 0;  i < length; i++)
356 			*p++ = io_read8((uint8_t *)hw->dev_cfg + offset + i);
357 
358 		new_gen = io_read8(&hw->common_cfg->config_generation);
359 	} while (old_gen != new_gen);
360 }
361 
362 static void
363 modern_write_dev_config(struct virtio_hw *hw, size_t offset,
364 			const void *src, int length)
365 {
366 	int i;
367 	const uint8_t *p = src;
368 
369 	for (i = 0;  i < length; i++)
370 		io_write8(*p++, (uint8_t *)hw->dev_cfg + offset + i);
371 }
372 
373 static uint64_t
374 modern_get_features(struct virtio_hw *hw)
375 {
376 	uint32_t features_lo, features_hi;
377 
378 	io_write32(0, &hw->common_cfg->device_feature_select);
379 	features_lo = io_read32(&hw->common_cfg->device_feature);
380 
381 	io_write32(1, &hw->common_cfg->device_feature_select);
382 	features_hi = io_read32(&hw->common_cfg->device_feature);
383 
384 	return ((uint64_t)features_hi << 32) | features_lo;
385 }
386 
387 static void
388 modern_set_features(struct virtio_hw *hw, uint64_t features)
389 {
390 	io_write32(0, &hw->common_cfg->guest_feature_select);
391 	io_write32(features & ((1ULL << 32) - 1),
392 		&hw->common_cfg->guest_feature);
393 
394 	io_write32(1, &hw->common_cfg->guest_feature_select);
395 	io_write32(features >> 32,
396 		&hw->common_cfg->guest_feature);
397 }
398 
399 static uint8_t
400 modern_get_status(struct virtio_hw *hw)
401 {
402 	return io_read8(&hw->common_cfg->device_status);
403 }
404 
405 static void
406 modern_set_status(struct virtio_hw *hw, uint8_t status)
407 {
408 	io_write8(status, &hw->common_cfg->device_status);
409 }
410 
411 static void
412 modern_reset(struct virtio_hw *hw)
413 {
414 	modern_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
415 	modern_get_status(hw);
416 }
417 
418 static uint8_t
419 modern_get_isr(struct virtio_hw *hw)
420 {
421 	return io_read8(hw->isr);
422 }
423 
424 static uint16_t
425 modern_set_config_irq(struct virtio_hw *hw, uint16_t vec)
426 {
427 	io_write16(vec, &hw->common_cfg->msix_config);
428 	return io_read16(&hw->common_cfg->msix_config);
429 }
430 
431 static uint16_t
432 modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
433 {
434 	io_write16(queue_id, &hw->common_cfg->queue_select);
435 	return io_read16(&hw->common_cfg->queue_size);
436 }
437 
438 static void
439 modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
440 {
441 	uint64_t desc_addr, avail_addr, used_addr;
442 	uint16_t notify_off;
443 
444 	desc_addr = vq->mz->phys_addr;
445 	avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
446 	used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
447 							 ring[vq->vq_nentries]),
448 				   VIRTIO_PCI_VRING_ALIGN);
449 
450 	io_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
451 
452 	io_write64_twopart(desc_addr, &hw->common_cfg->queue_desc_lo,
453 				      &hw->common_cfg->queue_desc_hi);
454 	io_write64_twopart(avail_addr, &hw->common_cfg->queue_avail_lo,
455 				       &hw->common_cfg->queue_avail_hi);
456 	io_write64_twopart(used_addr, &hw->common_cfg->queue_used_lo,
457 				      &hw->common_cfg->queue_used_hi);
458 
459 	notify_off = io_read16(&hw->common_cfg->queue_notify_off);
460 	vq->notify_addr = (void *)((uint8_t *)hw->notify_base +
461 				notify_off * hw->notify_off_multiplier);
462 
463 	io_write16(1, &hw->common_cfg->queue_enable);
464 
465 	PMD_INIT_LOG(DEBUG, "queue %u addresses:", vq->vq_queue_index);
466 	PMD_INIT_LOG(DEBUG, "\t desc_addr: %" PRIx64, desc_addr);
467 	PMD_INIT_LOG(DEBUG, "\t aval_addr: %" PRIx64, avail_addr);
468 	PMD_INIT_LOG(DEBUG, "\t used_addr: %" PRIx64, used_addr);
469 	PMD_INIT_LOG(DEBUG, "\t notify addr: %p (notify offset: %u)",
470 		vq->notify_addr, notify_off);
471 }
472 
473 static void
474 modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
475 {
476 	io_write16(vq->vq_queue_index, &hw->common_cfg->queue_select);
477 
478 	io_write64_twopart(0, &hw->common_cfg->queue_desc_lo,
479 				  &hw->common_cfg->queue_desc_hi);
480 	io_write64_twopart(0, &hw->common_cfg->queue_avail_lo,
481 				  &hw->common_cfg->queue_avail_hi);
482 	io_write64_twopart(0, &hw->common_cfg->queue_used_lo,
483 				  &hw->common_cfg->queue_used_hi);
484 
485 	io_write16(0, &hw->common_cfg->queue_enable);
486 }
487 
488 static void
489 modern_notify_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq)
490 {
491 	io_write16(1, vq->notify_addr);
492 }
493 
494 static const struct virtio_pci_ops modern_ops = {
495 	.read_dev_cfg	= modern_read_dev_config,
496 	.write_dev_cfg	= modern_write_dev_config,
497 	.reset		= modern_reset,
498 	.get_status	= modern_get_status,
499 	.set_status	= modern_set_status,
500 	.get_features	= modern_get_features,
501 	.set_features	= modern_set_features,
502 	.get_isr	= modern_get_isr,
503 	.set_config_irq	= modern_set_config_irq,
504 	.get_queue_num	= modern_get_queue_num,
505 	.setup_queue	= modern_setup_queue,
506 	.del_queue	= modern_del_queue,
507 	.notify_queue	= modern_notify_queue,
508 };
509 
510 
511 void
512 vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
513 		      void *dst, int length)
514 {
515 	hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length);
516 }
517 
518 void
519 vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
520 		       const void *src, int length)
521 {
522 	hw->vtpci_ops->write_dev_cfg(hw, offset, src, length);
523 }
524 
525 uint64_t
526 vtpci_negotiate_features(struct virtio_hw *hw, uint64_t host_features)
527 {
528 	uint64_t features;
529 
530 	/*
531 	 * Limit negotiated features to what the driver, virtqueue, and
532 	 * host all support.
533 	 */
534 	features = host_features & hw->guest_features;
535 	hw->vtpci_ops->set_features(hw, features);
536 
537 	return features;
538 }
539 
540 void
541 vtpci_reset(struct virtio_hw *hw)
542 {
543 	hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
544 	/* flush status write */
545 	hw->vtpci_ops->get_status(hw);
546 }
547 
548 void
549 vtpci_reinit_complete(struct virtio_hw *hw)
550 {
551 	vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
552 }
553 
554 void
555 vtpci_set_status(struct virtio_hw *hw, uint8_t status)
556 {
557 	if (status != VIRTIO_CONFIG_STATUS_RESET)
558 		status |= hw->vtpci_ops->get_status(hw);
559 
560 	hw->vtpci_ops->set_status(hw, status);
561 }
562 
563 uint8_t
564 vtpci_get_status(struct virtio_hw *hw)
565 {
566 	return hw->vtpci_ops->get_status(hw);
567 }
568 
569 uint8_t
570 vtpci_isr(struct virtio_hw *hw)
571 {
572 	return hw->vtpci_ops->get_isr(hw);
573 }
574 
575 
576 /* Enable one vector (0) for Link State Intrerrupt */
577 uint16_t
578 vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
579 {
580 	return hw->vtpci_ops->set_config_irq(hw, vec);
581 }
582 
583 static void *
584 get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
585 {
586 	uint8_t  bar    = cap->bar;
587 	uint32_t length = cap->length;
588 	uint32_t offset = cap->offset;
589 	uint8_t *base;
590 
591 	if (bar > 5) {
592 		PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
593 		return NULL;
594 	}
595 
596 	if (offset + length < offset) {
597 		PMD_INIT_LOG(ERR, "offset(%u) + length(%u) overflows",
598 			offset, length);
599 		return NULL;
600 	}
601 
602 	if (offset + length > dev->mem_resource[bar].len) {
603 		PMD_INIT_LOG(ERR,
604 			"invalid cap: overflows bar space: %u > %" PRIu64,
605 			offset + length, dev->mem_resource[bar].len);
606 		return NULL;
607 	}
608 
609 	base = dev->mem_resource[bar].addr;
610 	if (base == NULL) {
611 		PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
612 		return NULL;
613 	}
614 
615 	return base + offset;
616 }
617 
618 static int
619 virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
620 {
621 	uint8_t pos;
622 	struct virtio_pci_cap cap;
623 	int ret;
624 
625 	if (rte_eal_pci_map_device(dev)) {
626 		PMD_INIT_LOG(DEBUG, "failed to map pci device!");
627 		return -1;
628 	}
629 
630 	ret = rte_eal_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
631 	if (ret < 0) {
632 		PMD_INIT_LOG(DEBUG, "failed to read pci capability list");
633 		return -1;
634 	}
635 
636 	while (pos) {
637 		ret = rte_eal_pci_read_config(dev, &cap, sizeof(cap), pos);
638 		if (ret < 0) {
639 			PMD_INIT_LOG(ERR,
640 				"failed to read pci cap at pos: %x", pos);
641 			break;
642 		}
643 
644 		if (cap.cap_vndr != PCI_CAP_ID_VNDR) {
645 			PMD_INIT_LOG(DEBUG,
646 				"[%2x] skipping non VNDR cap id: %02x",
647 				pos, cap.cap_vndr);
648 			goto next;
649 		}
650 
651 		PMD_INIT_LOG(DEBUG,
652 			"[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u",
653 			pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
654 
655 		switch (cap.cfg_type) {
656 		case VIRTIO_PCI_CAP_COMMON_CFG:
657 			hw->common_cfg = get_cfg_addr(dev, &cap);
658 			break;
659 		case VIRTIO_PCI_CAP_NOTIFY_CFG:
660 			rte_eal_pci_read_config(dev, &hw->notify_off_multiplier,
661 						4, pos + sizeof(cap));
662 			hw->notify_base = get_cfg_addr(dev, &cap);
663 			break;
664 		case VIRTIO_PCI_CAP_DEVICE_CFG:
665 			hw->dev_cfg = get_cfg_addr(dev, &cap);
666 			break;
667 		case VIRTIO_PCI_CAP_ISR_CFG:
668 			hw->isr = get_cfg_addr(dev, &cap);
669 			break;
670 		}
671 
672 next:
673 		pos = cap.cap_next;
674 	}
675 
676 	if (hw->common_cfg == NULL || hw->notify_base == NULL ||
677 	    hw->dev_cfg == NULL    || hw->isr == NULL) {
678 		PMD_INIT_LOG(INFO, "no modern virtio pci device found.");
679 		return -1;
680 	}
681 
682 	PMD_INIT_LOG(INFO, "found modern virtio pci device.");
683 
684 	PMD_INIT_LOG(DEBUG, "common cfg mapped at: %p", hw->common_cfg);
685 	PMD_INIT_LOG(DEBUG, "device cfg mapped at: %p", hw->dev_cfg);
686 	PMD_INIT_LOG(DEBUG, "isr cfg mapped at: %p", hw->isr);
687 	PMD_INIT_LOG(DEBUG, "notify base: %p, notify off multiplier: %u",
688 		hw->notify_base, hw->notify_off_multiplier);
689 
690 	return 0;
691 }
692 
693 /*
694  * Return -1:
695  *   if there is error mapping with VFIO/UIO.
696  *   if port map error when driver type is KDRV_NONE.
697  * Return 1 if kernel driver is managing the device.
698  * Return 0 on success.
699  */
700 int
701 vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw,
702 	   uint32_t *dev_flags)
703 {
704 	hw->dev = dev;
705 
706 	/*
707 	 * Try if we can succeed reading virtio pci caps, which exists
708 	 * only on modern pci device. If failed, we fallback to legacy
709 	 * virtio handling.
710 	 */
711 	if (virtio_read_caps(dev, hw) == 0) {
712 		PMD_INIT_LOG(INFO, "modern virtio pci detected.");
713 		hw->vtpci_ops = &modern_ops;
714 		hw->modern    = 1;
715 		*dev_flags |= RTE_ETH_DEV_INTR_LSC;
716 		return 0;
717 	}
718 
719 	PMD_INIT_LOG(INFO, "trying with legacy virtio pci.");
720 	if (legacy_virtio_resource_init(dev, hw, dev_flags) < 0) {
721 		if (dev->kdrv == RTE_KDRV_UNKNOWN &&
722 		    dev->devargs->type != RTE_DEVTYPE_WHITELISTED_PCI) {
723 			PMD_INIT_LOG(INFO,
724 				"skip kernel managed virtio device.");
725 			return 1;
726 		}
727 		return -1;
728 	}
729 
730 	hw->vtpci_ops = &legacy_ops;
731 	hw->use_msix = legacy_virtio_has_msix(&dev->addr);
732 	hw->modern   = 0;
733 
734 	return 0;
735 }
736