Thread (120 messages) 120 messages, 7 authors, 2016-06-07
STALE3705d

[RFC PATCH 3/5] virtio: Add a new layer to abstract pci access method

From: Tetsuya Mukawa <hidden>
Date: 2016-01-21 11:08:16
Subsystem: networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

This patch addss function pointers to abstract pci access method.
This abstraction layer will be used when virtio-net PMD supports
container extension.

The below functions abstract how to access to pci configuration space.

struct virtio_pci_cfg_ops {
        int   (*map)(...);
        void  (*unmap)(...);
        void *(*get_mapped_addr)(...);
        int   (*read)(...);
};

The pci configuration space has information how to access to virtio
device registers. Basically, there are 2 ways to acccess to the
registers. One is using portio and the other is using mapped memory.
The below functions abstract this access method.

struct virtio_pci_dev_ops {
        uint8_t  (*read8)(...);
        uint16_t (*read16)(...);
        uint32_t (*read32)(...);
        void     (*write8)(...);
        void     (*write16)(...);
        void     (*write32)(...);
};

Signed-off-by: Tetsuya Mukawa <redacted>
---
 drivers/net/virtio/virtio_ethdev.c |   4 +-
 drivers/net/virtio/virtio_pci.c    | 519 ++++++++++++++++++++++++++-----------
 drivers/net/virtio/virtio_pci.h    |  24 +-
 3 files changed, 386 insertions(+), 161 deletions(-)
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 37833a8..c477b05 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1037,7 +1037,7 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
 
 	pci_dev = eth_dev->pci_dev;
 
-	if (vtpci_init(pci_dev, hw) < 0)
+	if (vtpci_init(eth_dev, hw) < 0)
 		return -1;
 
 	/* Reset the device although not necessary at startup */
@@ -1177,7 +1177,7 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev)
 		rte_intr_callback_unregister(&pci_dev->intr_handle,
 						virtio_interrupt_handler,
 						eth_dev);
-	vtpci_uninit(pci_dev, hw);
+	vtpci_uninit(eth_dev, hw);
 
 	PMD_INIT_LOG(DEBUG, "dev_uninit completed");
 
diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c
index 7d7ef06..98eef85 100644
--- a/drivers/net/virtio/virtio_pci.c
+++ b/drivers/net/virtio/virtio_pci.c
@@ -49,24 +49,198 @@
 #define PCI_CAPABILITY_LIST	0x34
 #define PCI_CAP_ID_VNDR		0x09
 
+static uint8_t
+phys_legacy_read8(struct virtio_hw *hw, uint8_t *addr)
+{
+	return inb((unsigned short)(hw->io_base + (uint64_t)addr));
+}
 
-#define VIRTIO_PCI_REG_ADDR(hw, reg) \
-	(unsigned short)((hw)->io_base + (reg))
+static uint16_t
+phys_legacy_read16(struct virtio_hw *hw, uint16_t *addr)
+{
+	return inw((unsigned short)(hw->io_base + (uint64_t)addr));
+}
 
-#define VIRTIO_READ_REG_1(hw, reg) \
-	inb((VIRTIO_PCI_REG_ADDR((hw), (reg))))
-#define VIRTIO_WRITE_REG_1(hw, reg, value) \
-	outb_p((unsigned char)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg))))
+static uint32_t
+phys_legacy_read32(struct virtio_hw *hw, uint32_t *addr)
+{
+	return inl((unsigned short)(hw->io_base + (uint64_t)addr));
+}
 
-#define VIRTIO_READ_REG_2(hw, reg) \
-	inw((VIRTIO_PCI_REG_ADDR((hw), (reg))))
-#define VIRTIO_WRITE_REG_2(hw, reg, value) \
-	outw_p((unsigned short)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg))))
+static void
+phys_legacy_write8(struct virtio_hw *hw, uint8_t *addr, uint8_t val)
+{
+	return outb_p((unsigned char)val,
+			(unsigned short)(hw->io_base + (uint64_t)addr));
+}
 
-#define VIRTIO_READ_REG_4(hw, reg) \
-	inl((VIRTIO_PCI_REG_ADDR((hw), (reg))))
-#define VIRTIO_WRITE_REG_4(hw, reg, value) \
-	outl_p((unsigned int)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg))))
+static void
+phys_legacy_write16(struct virtio_hw *hw, uint16_t *addr, uint16_t val)
+{
+	return outb_p((unsigned short)val,
+			(unsigned short)(hw->io_base + (uint64_t)addr));
+}
+
+static void
+phys_legacy_write32(struct virtio_hw *hw, uint32_t *addr, uint32_t val)
+{
+	return outb_p((unsigned int)val,
+			(unsigned short)(hw->io_base + (uint64_t)addr));
+}
+
+static const struct virtio_pci_dev_ops phys_legacy_dev_ops = {
+	.read8		= phys_legacy_read8,
+	.read16		= phys_legacy_read16,
+	.read32		= phys_legacy_read32,
+	.write8		= phys_legacy_write8,
+	.write16	= phys_legacy_write16,
+	.write32	= phys_legacy_write32,
+};
+
+static uint8_t
+phys_modern_read8(struct virtio_hw *hw __rte_unused, uint8_t *addr)
+{
+	return *(volatile uint8_t *)addr;
+}
+
+static uint16_t
+phys_modern_read16(struct virtio_hw *hw __rte_unused, uint16_t *addr)
+{
+	return *(volatile uint16_t *)addr;
+}
+
+static uint32_t
+phys_modern_read32(struct virtio_hw *hw __rte_unused, uint32_t *addr)
+{
+	return *(volatile uint32_t *)addr;
+}
+
+static void
+phys_modern_write8(struct virtio_hw *hw __rte_unused,
+		uint8_t *addr, uint8_t val)
+{
+	*(volatile uint8_t *)addr = val;
+}
+
+static void
+phys_modern_write16(struct virtio_hw *hw __rte_unused,
+		uint16_t *addr, uint16_t val)
+{
+	*(volatile uint16_t *)addr = val;
+}
+
+static void
+phys_modern_write32(struct virtio_hw *hw __rte_unused,
+		uint32_t *addr, uint32_t val)
+{
+	*(volatile uint32_t *)addr = val;
+}
+
+static const struct virtio_pci_dev_ops phys_modern_dev_ops = {
+	.read8		= phys_modern_read8,
+	.read16		= phys_modern_read16,
+	.read32		= phys_modern_read32,
+	.write8		= phys_modern_write8,
+	.write16	= phys_modern_write16,
+	.write32	= phys_modern_write32,
+};
+
+static int
+vtpci_dev_init(struct rte_eth_dev *dev, struct virtio_hw *hw)
+{
+	if (dev->dev_type == RTE_ETH_DEV_PCI) {
+		if (hw->modern == 1)
+			hw->vtpci_dev_ops = &phys_modern_dev_ops;
+		else
+			hw->vtpci_dev_ops = &phys_legacy_dev_ops;
+		return 0;
+	}
+
+	PMD_DRV_LOG(ERR, "Unkown virtio-net device.");
+	return -1;
+}
+
+static void
+vtpci_dev_uninit(struct rte_eth_dev *dev __rte_unused, struct virtio_hw *hw)
+{
+	hw->vtpci_dev_ops = NULL;
+}
+
+static int
+phys_map_pci_cfg(struct virtio_hw *hw)
+{
+	return rte_eal_pci_map_device(hw->dev);
+}
+
+static void
+phys_unmap_pci_cfg(struct virtio_hw *hw)
+{
+	rte_eal_pci_unmap_device(hw->dev);
+}
+
+static int
+phys_read_pci_cfg(struct virtio_hw *hw, void *buf, size_t len, off_t offset)
+{
+	return rte_eal_pci_read_config(hw->dev, buf, len, offset);
+}
+
+static void *
+phys_get_mapped_addr(struct virtio_hw *hw, uint8_t bar,
+		     uint32_t offset, uint32_t length)
+{
+	uint8_t *base;
+
+	if (bar > 5) {
+		PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
+		return NULL;
+	}
+
+	if (offset + length < offset) {
+		PMD_INIT_LOG(ERR, "offset(%u) + lenght(%u) overflows",
+			offset, length);
+		return NULL;
+	}
+
+	if (offset + length > hw->dev->mem_resource[bar].len) {
+		PMD_INIT_LOG(ERR,
+			"invalid cap: overflows bar space: %u > %"PRIu64,
+			offset + length, hw->dev->mem_resource[bar].len);
+		return NULL;
+	}
+
+	base = hw->dev->mem_resource[bar].addr;
+	if (base == NULL) {
+		PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
+		return NULL;
+	}
+
+	return base + offset;
+}
+
+static const struct virtio_pci_cfg_ops phys_cfg_ops = {
+	.map			= phys_map_pci_cfg,
+	.unmap			= phys_unmap_pci_cfg,
+	.get_mapped_addr	= phys_get_mapped_addr,
+	.read			= phys_read_pci_cfg,
+};
+
+static int
+vtpci_cfg_init(struct rte_eth_dev *dev, struct virtio_hw *hw)
+{
+	if (dev->dev_type == RTE_ETH_DEV_PCI) {
+		hw->vtpci_cfg_ops = &phys_cfg_ops;
+		return 0;
+	}
+
+	PMD_DRV_LOG(ERR, "Unkown virtio-net device.");
+	return -1;
+}
+
+static void
+vtpci_cfg_uninit(struct rte_eth_dev *dev __rte_unused, struct virtio_hw *hw)
+{
+	hw->vtpci_cfg_ops = NULL;
+}
 
 static void
 legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
@@ -80,13 +254,16 @@ legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
 	for (d = dst; length > 0; d += size, off += size, length -= size) {
 		if (length >= 4) {
 			size = 4;
-			*(uint32_t *)d = VIRTIO_READ_REG_4(hw, off);
+			*(uint32_t *)d = hw->vtpci_dev_ops->read32(
+						hw, (uint32_t *)off);
 		} else if (length >= 2) {
 			size = 2;
-			*(uint16_t *)d = VIRTIO_READ_REG_2(hw, off);
+			*(uint16_t *)d = hw->vtpci_dev_ops->read16(
+						hw, (uint16_t *)off);
 		} else {
 			size = 1;
-			*d = VIRTIO_READ_REG_1(hw, off);
+			*d = hw->vtpci_dev_ops->read8(
+						hw, (uint8_t *)off);
 		}
 	}
 }
@@ -103,13 +280,15 @@ legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
 	for (s = src; length > 0; s += size, off += size, length -= size) {
 		if (length >= 4) {
 			size = 4;
-			VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s);
+			hw->vtpci_dev_ops->write32(hw,
+					(uint32_t *)off, *(const uint32_t *)s);
 		} else if (length >= 2) {
 			size = 2;
-			VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s);
+			hw->vtpci_dev_ops->write16(hw,
+					(uint16_t *)off, *(const uint16_t *)s);
 		} else {
 			size = 1;
-			VIRTIO_WRITE_REG_1(hw, off, *s);
+			hw->vtpci_dev_ops->write8(hw, (uint8_t *)off, *s);
 		}
 	}
 }
@@ -117,7 +296,8 @@ legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
 static uint64_t
 legacy_get_features(struct virtio_hw *hw)
 {
-	return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
+	return hw->vtpci_dev_ops->read32(hw,
+			(uint32_t *)VIRTIO_PCI_HOST_FEATURES);
 }
 
 static void
@@ -128,19 +308,20 @@ legacy_set_features(struct virtio_hw *hw, uint64_t features)
 			"only 32 bit features are allowed for legacy virtio!");
 		return;
 	}
-	VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
+	hw->vtpci_dev_ops->write32(hw,
+			(uint32_t *)VIRTIO_PCI_GUEST_FEATURES, features);
 }
 
 static uint8_t
 legacy_get_status(struct virtio_hw *hw)
 {
-	return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
+	return hw->vtpci_dev_ops->read8(hw, (uint8_t *)VIRTIO_PCI_STATUS);
 }
 
 static void
 legacy_set_status(struct virtio_hw *hw, uint8_t status)
 {
-	VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
+	hw->vtpci_dev_ops->write8(hw, (uint8_t *)VIRTIO_PCI_STATUS, status);
 }
 
 static void
@@ -152,45 +333,55 @@ legacy_reset(struct virtio_hw *hw)
 static uint8_t
 legacy_get_isr(struct virtio_hw *hw)
 {
-	return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
+	return hw->vtpci_dev_ops->read8(hw, (uint8_t *)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);
+	hw->vtpci_dev_ops->write16(hw,
+			(uint16_t *)VIRTIO_MSI_CONFIG_VECTOR, vec);
+	return hw->vtpci_dev_ops->read16(hw,
+			(uint16_t *)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);
+	hw->vtpci_dev_ops->write16(hw,
+			(uint16_t *)VIRTIO_PCI_QUEUE_SEL, queue_id);
+	return hw->vtpci_dev_ops->read16(hw,
+			(uint16_t *)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);
+	hw->vtpci_dev_ops->write16(hw,
+			(uint16_t *)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);
+	hw->vtpci_dev_ops->write32(hw,
+			(uint32_t *)VIRTIO_PCI_QUEUE_PFN,
+			vq->vq_ring_mem >> 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);
+	hw->vtpci_dev_ops->write16(hw,
+			(uint16_t *)VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
 
-	VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
+	hw->vtpci_dev_ops->write32(hw,
+			(uint32_t *)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);
+	hw->vtpci_dev_ops->write16(hw,
+			(uint16_t *)VIRTIO_PCI_QUEUE_NOTIFY,
+			vq->vq_queue_index);
 }
 
 #ifdef RTE_EXEC_ENV_LINUXAPP
@@ -468,35 +659,12 @@ static const struct virtio_pci_ops legacy_ops = {
 	.notify_queue	= legacy_notify_queue,
 };
 
-
-#define IO_READ_DEF(nr_bits, type)		\
-static inline type				\
-io_read##nr_bits(type *addr)			\
-{						\
-	return *(volatile type *)addr;		\
-}
-
-#define IO_WRITE_DEF(nr_bits, type)		\
-static inline void				\
-io_write##nr_bits(type *addr, type val)		\
-{						\
-	*(volatile type *)addr = val;		\
-}
-
-IO_READ_DEF (8, uint8_t)
-IO_WRITE_DEF(8, uint8_t)
-
-IO_READ_DEF (16, uint16_t)
-IO_WRITE_DEF(16, uint16_t)
-
-IO_READ_DEF (32, uint32_t)
-IO_WRITE_DEF(32, uint32_t)
-
 static inline void
-io_write64_twopart(uint32_t *lo, uint32_t *hi, uint64_t val)
+io_write64_twopart(struct virtio_hw *hw,
+		   uint32_t *lo, uint32_t *hi, uint64_t val)
 {
-	io_write32(lo, val & ((1ULL << 32) - 1));
-	io_write32(hi, val >> 32);
+	hw->vtpci_dev_ops->write32(hw, lo, val & ((1ULL << 32) - 1));
+	hw->vtpci_dev_ops->write32(hw, hi, val >> 32);
 }
 
 static void
@@ -508,13 +676,16 @@ modern_read_dev_config(struct virtio_hw *hw, size_t offset,
 	uint8_t old_gen, new_gen;
 
 	do {
-		old_gen = io_read8(&hw->common_cfg->config_generation);
+		old_gen = hw->vtpci_dev_ops->read8(hw,
+				&hw->common_cfg->config_generation);
 
 		p = dst;
 		for (i = 0;  i < length; i++)
-			*p++ = io_read8((uint8_t *)hw->dev_cfg + offset + i);
+			*p++ = hw->vtpci_dev_ops->read8(hw,
+					(uint8_t *)hw->dev_cfg + offset + i);
 
-		new_gen = io_read8(&hw->common_cfg->config_generation);
+		new_gen = hw->vtpci_dev_ops->read8(hw,
+				&hw->common_cfg->config_generation);
 	} while (old_gen != new_gen);
 }
 
@@ -526,7 +697,8 @@ modern_write_dev_config(struct virtio_hw *hw, size_t offset,
 	const uint8_t *p = src;
 
 	for (i = 0;  i < length; i++)
-		io_write8((uint8_t *)hw->dev_cfg + offset + i, *p++);
+		hw->vtpci_dev_ops->write8(hw,
+				(uint8_t *)hw->dev_cfg + offset + i, *p++);
 }
 
 static uint64_t
@@ -534,11 +706,15 @@ modern_get_features(struct virtio_hw *hw)
 {
 	uint32_t features_lo, features_hi;
 
-	io_write32(&hw->common_cfg->device_feature_select, 0);
-	features_lo = io_read32(&hw->common_cfg->device_feature);
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->device_feature_select, 0);
+	features_lo = hw->vtpci_dev_ops->read32(hw,
+			&hw->common_cfg->device_feature);
 
-	io_write32(&hw->common_cfg->device_feature_select, 1);
-	features_hi = io_read32(&hw->common_cfg->device_feature);
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->device_feature_select, 1);
+	features_hi = hw->vtpci_dev_ops->read32(hw,
+			&hw->common_cfg->device_feature);
 
 	return ((uint64_t)features_hi << 32) | features_lo;
 }
@@ -546,25 +722,30 @@ modern_get_features(struct virtio_hw *hw)
 static void
 modern_set_features(struct virtio_hw *hw, uint64_t features)
 {
-	io_write32(&hw->common_cfg->guest_feature_select, 0);
-	io_write32(&hw->common_cfg->guest_feature,
-		   features & ((1ULL << 32) - 1));
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->guest_feature_select, 0);
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->guest_feature,
+			features & ((1ULL << 32) - 1));
 
-	io_write32(&hw->common_cfg->guest_feature_select, 1);
-	io_write32(&hw->common_cfg->guest_feature,
-		   features >> 32);
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->guest_feature_select, 1);
+	hw->vtpci_dev_ops->write32(hw,
+			&hw->common_cfg->guest_feature, features >> 32);
 }
 
 static uint8_t
 modern_get_status(struct virtio_hw *hw)
 {
-	return io_read8(&hw->common_cfg->device_status);
+	return hw->vtpci_dev_ops->read8(hw,
+			&hw->common_cfg->device_status);
 }
 
 static void
 modern_set_status(struct virtio_hw *hw, uint8_t status)
 {
-	io_write8(&hw->common_cfg->device_status, status);
+	hw->vtpci_dev_ops->write8(hw,
+			&hw->common_cfg->device_status, status);
 }
 
 static void
@@ -577,21 +758,25 @@ modern_reset(struct virtio_hw *hw)
 static uint8_t
 modern_get_isr(struct virtio_hw *hw)
 {
-	return io_read8(hw->isr);
+	return hw->vtpci_dev_ops->read8(hw, hw->isr);
 }
 
 static uint16_t
 modern_set_config_irq(struct virtio_hw *hw, uint16_t vec)
 {
-	io_write16(&hw->common_cfg->msix_config, vec);
-	return io_read16(&hw->common_cfg->msix_config);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->msix_config, vec);
+	return hw->vtpci_dev_ops->read16(hw,
+			&hw->common_cfg->msix_config);
 }
 
 static uint16_t
 modern_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
 {
-	io_write16(&hw->common_cfg->queue_select, queue_id);
-	return io_read16(&hw->common_cfg->queue_size);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->queue_select, queue_id);
+	return hw->vtpci_dev_ops->read16(hw,
+			&hw->common_cfg->queue_size);
 }
 
 static void
@@ -606,20 +791,23 @@ modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
 							 ring[vq->vq_nentries]),
 				   VIRTIO_PCI_VRING_ALIGN);
 
-	io_write16(&hw->common_cfg->queue_select, vq->vq_queue_index);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->queue_select, vq->vq_queue_index);
 
-	io_write64_twopart(&hw->common_cfg->queue_desc_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_desc_lo,
 			   &hw->common_cfg->queue_desc_hi, desc_addr);
-	io_write64_twopart(&hw->common_cfg->queue_avail_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_avail_lo,
 			   &hw->common_cfg->queue_avail_hi, avail_addr);
-	io_write64_twopart(&hw->common_cfg->queue_used_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_used_lo,
 			   &hw->common_cfg->queue_used_hi, used_addr);
 
-	notify_off = io_read16(&hw->common_cfg->queue_notify_off);
+	notify_off = hw->vtpci_dev_ops->read16(hw,
+				&hw->common_cfg->queue_notify_off);
 	vq->notify_addr = (void *)((uint8_t *)hw->notify_base +
 				notify_off * hw->notify_off_multiplier);
 
-	io_write16(&hw->common_cfg->queue_enable, 1);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->queue_enable, 1);
 
 	PMD_INIT_LOG(DEBUG, "queue %u addresses:", vq->vq_queue_index);
 	PMD_INIT_LOG(DEBUG, "\t desc_addr: %"PRIx64, desc_addr);
@@ -632,22 +820,24 @@ modern_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
 static void
 modern_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
 {
-	io_write16(&hw->common_cfg->queue_select, vq->vq_queue_index);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->queue_select, vq->vq_queue_index);
 
-	io_write64_twopart(&hw->common_cfg->queue_desc_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_desc_lo,
 			   &hw->common_cfg->queue_desc_hi, 0);
-	io_write64_twopart(&hw->common_cfg->queue_avail_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_avail_lo,
 			   &hw->common_cfg->queue_avail_hi, 0);
-	io_write64_twopart(&hw->common_cfg->queue_used_lo,
+	io_write64_twopart(hw, &hw->common_cfg->queue_used_lo,
 			   &hw->common_cfg->queue_used_hi, 0);
 
-	io_write16(&hw->common_cfg->queue_enable, 0);
+	hw->vtpci_dev_ops->write16(hw,
+			&hw->common_cfg->queue_enable, 0);
 }
 
 static void
 modern_notify_queue(struct virtio_hw *hw __rte_unused, struct virtqueue *vq)
 {
-	io_write16(vq->notify_addr, 1);
+	hw->vtpci_dev_ops->write16(hw, vq->notify_addr, 1);
 }
 
 static const struct virtio_pci_ops modern_ops = {
@@ -666,7 +856,6 @@ static const struct virtio_pci_ops modern_ops = {
 	.notify_queue	= modern_notify_queue,
 };
 
-
 void
 vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
 		      void *dst, int length)
@@ -739,61 +928,26 @@ vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
 	return hw->vtpci_ops->set_config_irq(hw, vec);
 }
 
-static void *
-get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)
-{
-	uint8_t  bar    = cap->bar;
-	uint32_t length = cap->length;
-	uint32_t offset = cap->offset;
-	uint8_t *base;
-
-	if (bar > 5) {
-		PMD_INIT_LOG(ERR, "invalid bar: %u", bar);
-		return NULL;
-	}
-
-	if (offset + length < offset) {
-		PMD_INIT_LOG(ERR, "offset(%u) + lenght(%u) overflows",
-			offset, length);
-		return NULL;
-	}
-
-	if (offset + length > dev->mem_resource[bar].len) {
-		PMD_INIT_LOG(ERR,
-			"invalid cap: overflows bar space: %u > %"PRIu64,
-			offset + length, dev->mem_resource[bar].len);
-		return NULL;
-	}
-
-	base = dev->mem_resource[bar].addr;
-	if (base == NULL) {
-		PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
-		return NULL;
-	}
-
-	return base + offset;
-}
-
 static int
-virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
+virtio_read_caps(struct virtio_hw *hw)
 {
 	uint8_t pos;
 	struct virtio_pci_cap cap;
 	int ret;
 
-	if (rte_eal_pci_map_device(dev) < 0) {
+	if (hw->vtpci_cfg_ops->map(hw) < 0) {
 		PMD_INIT_LOG(DEBUG, "failed to map pci device!");
 		return -1;
 	}
 
-	ret = rte_eal_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);
+	ret = hw->vtpci_cfg_ops->read(hw, &pos, 1, PCI_CAPABILITY_LIST);
 	if (ret < 0) {
 		PMD_INIT_LOG(DEBUG, "failed to read pci capability list");
 		return -1;
 	}
 
 	while (pos) {
-		ret = rte_eal_pci_read_config(dev, &cap, sizeof(cap), pos);
+		ret = hw->vtpci_cfg_ops->read(hw, &cap, sizeof(cap), pos);
 		if (ret < 0) {
 			PMD_INIT_LOG(ERR,
 				"failed to read pci cap at pos: %x", pos);
@@ -813,18 +967,25 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
 
 		switch (cap.cfg_type) {
 		case VIRTIO_PCI_CAP_COMMON_CFG:
-			hw->common_cfg = get_cfg_addr(dev, &cap);
+			hw->common_cfg =
+				hw->vtpci_cfg_ops->get_mapped_addr(
+					hw, cap.bar, cap.offset, cap.length);
 			break;
 		case VIRTIO_PCI_CAP_NOTIFY_CFG:
-			rte_eal_pci_read_config(dev, &hw->notify_off_multiplier,
+			hw->vtpci_cfg_ops->read(hw, &hw->notify_off_multiplier,
 						4, pos + sizeof(cap));
-			hw->notify_base = get_cfg_addr(dev, &cap);
+			hw->notify_base =
+				hw->vtpci_cfg_ops->get_mapped_addr(
+					hw, cap.bar, cap.offset, cap.length);
 			break;
 		case VIRTIO_PCI_CAP_DEVICE_CFG:
-			hw->dev_cfg = get_cfg_addr(dev, &cap);
+			hw->dev_cfg =
+				hw->vtpci_cfg_ops->get_mapped_addr(
+					hw, cap.bar, cap.offset, cap.length);
 			break;
 		case VIRTIO_PCI_CAP_ISR_CFG:
-			hw->isr = get_cfg_addr(dev, &cap);
+			hw->isr = hw->vtpci_cfg_ops->get_mapped_addr(
+					hw, cap.bar, cap.offset, cap.length);
 			break;
 		}
 
@@ -849,43 +1010,87 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_hw *hw)
 	return 0;
 }
 
+static int
+vtpci_modern_init(struct rte_eth_dev *dev, struct virtio_hw *hw)
+{
+	struct rte_pci_device *pci_dev = dev->pci_dev;
+
+	PMD_INIT_LOG(INFO, "modern virtio pci detected.");
+
+	if (dev->dev_type == RTE_ETH_DEV_PCI)
+		pci_dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC;
+
+	hw->vtpci_ops = &modern_ops;
+	hw->modern = 1;
+
+	return 0;
+}
+
+static int
+vtpci_legacy_init(struct rte_eth_dev *dev, struct virtio_hw *hw)
+{
+	struct rte_pci_device *pci_dev = dev->pci_dev;
+
+	PMD_INIT_LOG(INFO, "trying with legacy virtio pci.");
+	if (dev->dev_type == RTE_ETH_DEV_PCI) {
+		if (legacy_virtio_resource_init(pci_dev) < 0)
+			return -1;
+
+		hw->use_msix = legacy_virtio_has_msix(&pci_dev->addr);
+	}
+
+	hw->io_base = (uint32_t)(uintptr_t)
+		hw->vtpci_cfg_ops->get_mapped_addr(hw, 0, 0, 0);
+	hw->vtpci_ops = &legacy_ops;
+	hw->modern = 0;
+
+	return 0;
+}
+
 int
-vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw)
+vtpci_init(struct rte_eth_dev *eth_dev, struct virtio_hw *hw)
 {
-	hw->dev = dev;
+	struct rte_pci_device *pci_dev = eth_dev->pci_dev;
+	int ret;
+
+	hw->dev = pci_dev;
+
+	if ((eth_dev->dev_type == RTE_ETH_DEV_PCI) && (pci_dev == NULL)) {
+		PMD_INIT_LOG(INFO, "No pci device specified.");
+		return -1;
+	}
+
+	if (vtpci_cfg_init(eth_dev, hw) < 0)
+		return -1;
 
 	/*
 	 * Try if we can succeed reading virtio pci caps, which exists
 	 * only on modern pci device. If failed, we fallback to legacy
 	 * virtio handling.
 	 */
-	if (virtio_read_caps(dev, hw) == 0) {
-		PMD_INIT_LOG(INFO, "modern virtio pci detected.");
-		hw->vtpci_ops = &modern_ops;
-		hw->modern    = 1;
-		dev->driver->drv_flags |= RTE_PCI_DRV_INTR_LSC;
-		return 0;
-	}
+	if (virtio_read_caps(hw) == 0)
+		ret = vtpci_modern_init(eth_dev, hw);
+	else
+		ret = vtpci_legacy_init(eth_dev, hw);
 
-	PMD_INIT_LOG(INFO, "trying with legacy virtio pci.");
-	if (legacy_virtio_resource_init(dev) < 0)
+	if (ret < 0)
 		return -1;
 
-	hw->vtpci_ops = &legacy_ops;
-	hw->use_msix = legacy_virtio_has_msix(&dev->addr);
-	hw->io_base  = (uint32_t)(uintptr_t)dev->mem_resource[0].addr;
-	hw->modern   = 0;
+	if (vtpci_dev_init(eth_dev, hw) < 0)
+		return -1;
 
 	return 0;
 }
 
 void
-vtpci_uninit(struct rte_pci_device *dev, struct virtio_hw *hw)
+vtpci_uninit(struct rte_eth_dev *eth_dev, struct virtio_hw *hw)
 {
 	hw->dev  = NULL;
 	hw->vtpci_ops = NULL;
 	hw->use_msix = 0;
 	hw->io_base  = 0;
 	hw->modern   = 0;
-	rte_eal_pci_unmap_device(dev);
+	hw->vtpci_cfg_ops->unmap(hw);
+	vtpci_dev_uninit(eth_dev, hw);
+	vtpci_cfg_uninit(eth_dev, hw);
 }
diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h
index 17c7972..7b5ad54 100644
--- a/drivers/net/virtio/virtio_pci.h
+++ b/drivers/net/virtio/virtio_pci.h
@@ -222,6 +222,24 @@ struct virtio_pci_common_cfg {
 
 struct virtio_hw;
 
+/* Functions to access pci configuration space */
+struct virtio_pci_cfg_ops {
+	int (*map)(struct virtio_hw *hw);
+	void (*unmap)(struct virtio_hw *hw);
+	void *(*get_mapped_addr)(struct virtio_hw *hw, uint8_t bar, uint32_t offset, uint32_t length);
+	int (*read)(struct virtio_hw *hw, void *buf, size_t len, off_t offset);
+};
+
+/* Functions to access pci device registers */
+struct virtio_pci_dev_ops {
+	uint8_t (*read8)(struct virtio_hw *hw, uint8_t *addr);
+	uint16_t (*read16)(struct virtio_hw *hw, uint16_t *addr);
+	uint32_t (*read32)(struct virtio_hw *hw, uint32_t *addr);
+	void (*write8)(struct virtio_hw *hw, uint8_t *addr, uint8_t val);
+	void (*write16)(struct virtio_hw *hw, uint16_t *addr, uint16_t val);
+	void (*write32)(struct virtio_hw *hw, uint32_t *addr, uint32_t val);
+};
+
 struct virtio_pci_ops {
 	void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset,
 			     void *dst, int len);
@@ -266,6 +284,8 @@ struct virtio_hw {
 	struct virtio_pci_common_cfg *common_cfg;
 	struct virtio_net_config *dev_cfg;
 	const struct virtio_pci_ops *vtpci_ops;
+	const struct virtio_pci_cfg_ops *vtpci_cfg_ops;
+	const struct virtio_pci_dev_ops *vtpci_dev_ops;
 };
 
 /*
@@ -327,8 +347,8 @@ vtpci_with_feature(struct virtio_hw *hw, uint64_t bit)
 /*
  * Function declaration from virtio_pci.c
  */
-int vtpci_init(struct rte_pci_device *, struct virtio_hw *);
-void vtpci_uninit(struct rte_pci_device *dev, struct virtio_hw *);
+int vtpci_init(struct rte_eth_dev *, struct virtio_hw *);
+void vtpci_uninit(struct rte_eth_dev *, struct virtio_hw *);
 void vtpci_reset(struct virtio_hw *);
 
 void vtpci_reinit_complete(struct virtio_hw *);
-- 
2.1.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help