@@ -1287,8 +1287,8 @@ virtio_intr_unmask(struct rte_eth_dev *dev)
if (rte_intr_ack(dev->intr_handle) < 0)
return -1;
- if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY || hw->bus_type == VIRTIO_BUS_PCI_MODERN)
- hw->use_msix = vtpci_msix_detect(RTE_ETH_DEV_TO_PCI(dev));
+ if (VTPCI_OPS(hw)->intr_detect)
+ VTPCI_OPS(hw)->intr_detect(hw);
return 0;
}
@@ -1301,8 +1301,8 @@ virtio_intr_enable(struct rte_eth_dev *dev)
if (rte_intr_enable(dev->intr_handle) < 0)
return -1;
- if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY || hw->bus_type == VIRTIO_BUS_PCI_MODERN)
- hw->use_msix = vtpci_msix_detect(RTE_ETH_DEV_TO_PCI(dev));
+ if (VTPCI_OPS(hw)->intr_detect)
+ VTPCI_OPS(hw)->intr_detect(hw);
return 0;
}
@@ -1315,8 +1315,8 @@ virtio_intr_disable(struct rte_eth_dev *dev)
if (rte_intr_disable(dev->intr_handle) < 0)
return -1;
- if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY || hw->bus_type == VIRTIO_BUS_PCI_MODERN)
- hw->use_msix = vtpci_msix_detect(RTE_ETH_DEV_TO_PCI(dev));
+ if (VTPCI_OPS(hw)->intr_detect)
+ VTPCI_OPS(hw)->intr_detect(hw);
return 0;
}
@@ -47,6 +47,56 @@ check_vq_phys_addr_ok(struct virtqueue *vq)
return 1;
}
+#define PCI_MSIX_ENABLE 0x8000
+
+static enum virtio_msix_status
+vtpci_msix_detect(struct rte_pci_device *dev)
+{
+ uint8_t pos;
+ int ret;
+
+ ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
+ if (ret != 1) {
+ PMD_INIT_LOG(DEBUG,
+ "failed to read pci capability list, ret %d", ret);
+ return VIRTIO_MSIX_NONE;
+ }
+
+ while (pos) {
+ uint8_t cap[2];
+
+ ret = rte_pci_read_config(dev, cap, sizeof(cap), pos);
+ if (ret != sizeof(cap)) {
+ PMD_INIT_LOG(DEBUG,
+ "failed to read pci cap at pos: %x ret %d",
+ pos, ret);
+ break;
+ }
+
+ if (cap[0] == PCI_CAP_ID_MSIX) {
+ uint16_t flags;
+
+ ret = rte_pci_read_config(dev, &flags, sizeof(flags),
+ pos + sizeof(cap));
+ if (ret != sizeof(flags)) {
+ PMD_INIT_LOG(DEBUG,
+ "failed to read pci cap at pos:"
+ " %x ret %d", pos + 2, ret);
+ break;
+ }
+
+ if (flags & PCI_MSIX_ENABLE)
+ return VIRTIO_MSIX_ENABLED;
+ else
+ return VIRTIO_MSIX_DISABLED;
+ }
+
+ pos = cap[1];
+ }
+
+ return VIRTIO_MSIX_NONE;
+}
+
/*
* Since we are in legacy mode:
* http://ozlabs.org/~rusty/virtio-spec/virtio-0.9.5.pdf
@@ -241,6 +291,12 @@ legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
VIRTIO_PCI_QUEUE_NOTIFY);
}
+static void
+legacy_intr_detect(struct virtio_hw *hw)
+{
+ hw->use_msix = vtpci_msix_detect(VTPCI_DEV(hw));
+}
+
const struct virtio_pci_ops legacy_ops = {
.read_dev_cfg = legacy_read_dev_config,
.write_dev_cfg = legacy_write_dev_config,
@@ -255,6 +311,7 @@ const struct virtio_pci_ops legacy_ops = {
.setup_queue = legacy_setup_queue,
.del_queue = legacy_del_queue,
.notify_queue = legacy_notify_queue,
+ .intr_detect = legacy_intr_detect,
};
static inline void
@@ -446,6 +503,14 @@ modern_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
rte_write32(notify_data, vq->notify_addr);
}
+
+
+static void
+modern_intr_detect(struct virtio_hw *hw)
+{
+ hw->use_msix = vtpci_msix_detect(VTPCI_DEV(hw));
+}
+
const struct virtio_pci_ops modern_ops = {
.read_dev_cfg = modern_read_dev_config,
.write_dev_cfg = modern_write_dev_config,
@@ -460,6 +525,7 @@ const struct virtio_pci_ops modern_ops = {
.setup_queue = modern_setup_queue,
.del_queue = modern_del_queue,
.notify_queue = modern_notify_queue,
+ .intr_detect = modern_intr_detect,
};
@@ -562,8 +628,6 @@ get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
return base + offset;
}
-#define PCI_MSIX_ENABLE 0x8000
-
static int
virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
{
@@ -700,7 +764,7 @@ vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw)
PMD_INIT_LOG(INFO, "modern virtio pci detected.");
virtio_hw_internal[hw->port_id].vtpci_ops = &modern_ops;
hw->bus_type = VIRTIO_BUS_PCI_MODERN;
- return 0;
+ goto msix_detect;
}
PMD_INIT_LOG(INFO, "trying with legacy virtio pci.");
@@ -720,53 +784,9 @@ vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw)
virtio_hw_internal[hw->port_id].vtpci_ops = &legacy_ops;
hw->bus_type = VIRTIO_BUS_PCI_LEGACY;
+msix_detect:
+ VTPCI_OPS(hw)->intr_detect(hw);
+
return 0;
}
-enum virtio_msix_status
-vtpci_msix_detect(struct rte_pci_device *dev)
-{
- uint8_t pos;
- int ret;
-
- ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
- if (ret != 1) {
- PMD_INIT_LOG(DEBUG,
- "failed to read pci capability list, ret %d", ret);
- return VIRTIO_MSIX_NONE;
- }
-
- while (pos) {
- uint8_t cap[2];
-
- ret = rte_pci_read_config(dev, cap, sizeof(cap), pos);
- if (ret != sizeof(cap)) {
- PMD_INIT_LOG(DEBUG,
- "failed to read pci cap at pos: %x ret %d",
- pos, ret);
- break;
- }
-
- if (cap[0] == PCI_CAP_ID_MSIX) {
- uint16_t flags;
-
- ret = rte_pci_read_config(dev, &flags, sizeof(flags),
- pos + sizeof(cap));
- if (ret != sizeof(flags)) {
- PMD_INIT_LOG(DEBUG,
- "failed to read pci cap at pos:"
- " %x ret %d", pos + 2, ret);
- break;
- }
-
- if (flags & PCI_MSIX_ENABLE)
- return VIRTIO_MSIX_ENABLED;
- else
- return VIRTIO_MSIX_DISABLED;
- }
-
- pos = cap[1];
- }
-
- return VIRTIO_MSIX_NONE;
-}
@@ -239,6 +239,7 @@ struct virtio_pci_ops {
int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq);
void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq);
void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq);
+ void (*intr_detect)(struct virtio_hw *hw);
};
struct virtio_net_config;
@@ -303,10 +304,13 @@ struct virtio_pci_dev {
struct virtio_hw_internal {
const struct virtio_pci_ops *vtpci_ops;
struct rte_pci_ioport io;
+ struct rte_pci_device *dev;
};
#define VTPCI_OPS(hw) (virtio_hw_internal[(hw)->port_id].vtpci_ops)
#define VTPCI_IO(hw) (&virtio_hw_internal[(hw)->port_id].io)
+#define VTPCI_DEV(hw) (virtio_hw_internal[(hw)->port_id].dev)
+
extern struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS];
@@ -383,8 +387,6 @@ void vtpci_read_dev_config(struct virtio_hw *, size_t, void *, int);
uint8_t vtpci_isr(struct virtio_hw *);
-enum virtio_msix_status vtpci_msix_detect(struct rte_pci_device *dev);
-
extern const struct virtio_pci_ops legacy_ops;
extern const struct virtio_pci_ops modern_ops;
extern const struct virtio_pci_ops virtio_user_ops;
@@ -73,6 +73,8 @@ eth_virtio_pci_init(struct rte_eth_dev *eth_dev)
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
int ret;
+ VTPCI_DEV(hw) = pci_dev;
+
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
ret = vtpci_init(RTE_ETH_DEV_TO_PCI(eth_dev), hw);
if (ret) {