virtio: fix PCI accesses for ppc64 in legacy mode
[dpdk.git] / drivers / net / virtio / virtio_pci.c
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 }