summaryrefslogtreecommitdiff
path: root/drivers/net/virtio/virtio_pci.c
diff options
context:
space:
mode:
authorYuanhan Liu <yuanhan.liu@linux.intel.com>2016-02-02 21:48:14 +0800
committerThomas Monjalon <thomas.monjalon@6wind.com>2016-02-03 16:07:49 +0100
commitd5bbeefca82610c211b26390b0bd6a02704f10eb (patch)
tree2b486e2c8b922e8a300ec36c847fa989019765c9 /drivers/net/virtio/virtio_pci.c
parent4c2277ff45436eac87a3b0ff89235b465a7a4c5b (diff)
downloaddpdk-next-eventdev-d5bbeefca82610c211b26390b0bd6a02704f10eb.zip
dpdk-next-eventdev-d5bbeefca82610c211b26390b0bd6a02704f10eb.tar.gz
dpdk-next-eventdev-d5bbeefca82610c211b26390b0bd6a02704f10eb.tar.xz
virtio: introduce PCI implementation structure
Introduce struct virtio_pci_ops, to let legacy virtio (v0.95) and modern virtio (1.0) have different implementation regarding to a specific pci action, such as read host status. With that, this patch reimplements all exported pci functions, in a way like: vtpci_foo_bar(struct virtio_hw *hw) { hw->vtpci_ops->foo_bar(hw); } So that we need pay attention to those pci related functions only while adding virtio 1.0 support. This patch introduced a new vtpci function, vtpci_init(), to do proper virtio pci settings. It's pretty simple so far: just sets hw->vtpci_ops to legacy_ops as we don't support 1.0 yet. Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com> Tested-by: Qian Xu <qian.q.xu@intel.com> Reviewed-by: Tetsuya Mukawa <mukawa@igel.co.jp> Tested-by: Tetsuya Mukawa <mukawa@igel.co.jp> Acked-by: Huawei Xie <huawei.xie@intel.com>
Diffstat (limited to 'drivers/net/virtio/virtio_pci.c')
-rw-r--r--drivers/net/virtio/virtio_pci.c164
1 files changed, 133 insertions, 31 deletions
diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c
index b34b59e..8d001e8 100644
--- a/drivers/net/virtio/virtio_pci.c
+++ b/drivers/net/virtio/virtio_pci.c
@@ -34,12 +34,11 @@
#include "virtio_pci.h"
#include "virtio_logs.h"
+#include "virtqueue.h"
-static uint8_t vtpci_get_status(struct virtio_hw *);
-
-void
-vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
- void *dst, int length)
+static void
+legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
+ void *dst, int length)
{
uint64_t off;
uint8_t *d;
@@ -60,22 +59,22 @@ vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
}
}
-void
-vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
- void *src, int length)
+static void
+legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
+ const void *src, int length)
{
uint64_t off;
- uint8_t *s;
+ const uint8_t *s;
int size;
off = VIRTIO_PCI_CONFIG(hw) + offset;
for (s = src; length > 0; s += size, off += size, length -= size) {
if (length >= 4) {
size = 4;
- VIRTIO_WRITE_REG_4(hw, off, *(uint32_t *)s);
+ VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s);
} else if (length >= 2) {
size = 2;
- VIRTIO_WRITE_REG_2(hw, off, *(uint16_t *)s);
+ VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s);
} else {
size = 1;
VIRTIO_WRITE_REG_1(hw, off, *s);
@@ -83,30 +82,133 @@ vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
}
}
+static uint32_t
+legacy_get_features(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
+}
+
+static void
+legacy_set_features(struct virtio_hw *hw, uint32_t features)
+{
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
+}
+
+static uint8_t
+legacy_get_status(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
+}
+
+static void
+legacy_set_status(struct virtio_hw *hw, uint8_t status)
+{
+ VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
+}
+
+static void
+legacy_reset(struct virtio_hw *hw)
+{
+ legacy_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+}
+
+static uint8_t
+legacy_get_isr(struct virtio_hw *hw)
+{
+ return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
+}
+
+/* Enable one vector (0) for Link State Intrerrupt */
+static uint16_t
+legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
+ return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
+}
+
+static uint16_t
+legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, queue_id);
+ return VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
+}
+
+static void
+legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
+
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN,
+ vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
+}
+
+static void
+legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
+
+ VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
+}
+
+static void
+legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
+{
+ VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index);
+}
+
+
+static const struct virtio_pci_ops legacy_ops = {
+ .read_dev_cfg = legacy_read_dev_config,
+ .write_dev_cfg = legacy_write_dev_config,
+ .reset = legacy_reset,
+ .get_status = legacy_get_status,
+ .set_status = legacy_set_status,
+ .get_features = legacy_get_features,
+ .set_features = legacy_set_features,
+ .get_isr = legacy_get_isr,
+ .set_config_irq = legacy_set_config_irq,
+ .get_queue_num = legacy_get_queue_num,
+ .setup_queue = legacy_setup_queue,
+ .del_queue = legacy_del_queue,
+ .notify_queue = legacy_notify_queue,
+};
+
+
+void
+vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
+ void *dst, int length)
+{
+ hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length);
+}
+
+void
+vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
+ const void *src, int length)
+{
+ hw->vtpci_ops->write_dev_cfg(hw, offset, src, length);
+}
+
uint32_t
vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features)
{
uint32_t features;
+
/*
* Limit negotiated features to what the driver, virtqueue, and
* host all support.
*/
features = host_features & hw->guest_features;
+ hw->vtpci_ops->set_features(hw, features);
- VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
return features;
}
-
void
vtpci_reset(struct virtio_hw *hw)
{
- /*
- * Setting the status to RESET sets the host device to
- * the original, uninitialized state.
- */
- vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
- vtpci_get_status(hw);
+ hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
+ /* flush status write */
+ hw->vtpci_ops->get_status(hw);
}
void
@@ -115,26 +217,19 @@ vtpci_reinit_complete(struct virtio_hw *hw)
vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
}
-static uint8_t
-vtpci_get_status(struct virtio_hw *hw)
-{
- return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
-}
-
void
vtpci_set_status(struct virtio_hw *hw, uint8_t status)
{
if (status != VIRTIO_CONFIG_STATUS_RESET)
- status = (uint8_t)(status | vtpci_get_status(hw));
+ status |= hw->vtpci_ops->get_status(hw);
- VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
+ hw->vtpci_ops->set_status(hw, status);
}
uint8_t
vtpci_isr(struct virtio_hw *hw)
{
-
- return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
+ return hw->vtpci_ops->get_isr(hw);
}
@@ -142,6 +237,13 @@ vtpci_isr(struct virtio_hw *hw)
uint16_t
vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
{
- VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
- return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
+ return hw->vtpci_ops->set_config_irq(hw, vec);
+}
+
+int
+vtpci_init(struct rte_pci_device *dev __rte_unused, struct virtio_hw *hw)
+{
+ hw->vtpci_ops = &legacy_ops;
+
+ return 0;
}